New upstream version 4.7.2+ds
authorSimon McVittie <smcv@debian.org>
Thu, 11 Aug 2022 22:35:23 +0000 (23:35 +0100)
committerSimon McVittie <smcv@debian.org>
Thu, 11 Aug 2022 22:35:23 +0000 (23:35 +0100)
219 files changed:
1  2 
subprojects/wayland-protocols/.editorconfig
subprojects/wayland-protocols/.gitlab-ci.yml
subprojects/wayland-protocols/.gitlab-ci/debian-install.sh
subprojects/wayland-protocols/COPYING
subprojects/wayland-protocols/GOVERNANCE.md
subprojects/wayland-protocols/MEMBERS.md
subprojects/wayland-protocols/README.md
subprojects/wayland-protocols/meson.build
subprojects/wayland-protocols/meson_options.txt
subprojects/wayland-protocols/stable/presentation-time/README
subprojects/wayland-protocols/stable/presentation-time/presentation-time.xml
subprojects/wayland-protocols/stable/viewporter/README
subprojects/wayland-protocols/stable/viewporter/viewporter.xml
subprojects/wayland-protocols/stable/xdg-shell/README
subprojects/wayland-protocols/stable/xdg-shell/xdg-shell.xml
subprojects/wayland-protocols/staging/drm-lease/README
subprojects/wayland-protocols/staging/drm-lease/drm-lease-v1.xml
subprojects/wayland-protocols/staging/ext-session-lock/README
subprojects/wayland-protocols/staging/ext-session-lock/ext-session-lock-v1.xml
subprojects/wayland-protocols/staging/single-pixel-buffer/README
subprojects/wayland-protocols/staging/single-pixel-buffer/single-pixel-buffer-v1.xml
subprojects/wayland-protocols/staging/xdg-activation/README
subprojects/wayland-protocols/staging/xdg-activation/x11-interoperation.rst
subprojects/wayland-protocols/staging/xdg-activation/xdg-activation-v1.xml
subprojects/wayland-protocols/tests/build-cxx.cc.in
subprojects/wayland-protocols/tests/build-pedantic.c.in
subprojects/wayland-protocols/tests/meson.build
subprojects/wayland-protocols/tests/replace.py
subprojects/wayland-protocols/tests/scan.sh
subprojects/wayland-protocols/unstable/fullscreen-shell/README
subprojects/wayland-protocols/unstable/fullscreen-shell/fullscreen-shell-unstable-v1.xml
subprojects/wayland-protocols/unstable/idle-inhibit/README
subprojects/wayland-protocols/unstable/idle-inhibit/idle-inhibit-unstable-v1.xml
subprojects/wayland-protocols/unstable/input-method/README
subprojects/wayland-protocols/unstable/input-method/input-method-unstable-v1.xml
subprojects/wayland-protocols/unstable/input-timestamps/README
subprojects/wayland-protocols/unstable/input-timestamps/input-timestamps-unstable-v1.xml
subprojects/wayland-protocols/unstable/keyboard-shortcuts-inhibit/README
subprojects/wayland-protocols/unstable/keyboard-shortcuts-inhibit/keyboard-shortcuts-inhibit-unstable-v1.xml
subprojects/wayland-protocols/unstable/linux-dmabuf/README
subprojects/wayland-protocols/unstable/linux-dmabuf/feedback.rst
subprojects/wayland-protocols/unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml
subprojects/wayland-protocols/unstable/linux-explicit-synchronization/README
subprojects/wayland-protocols/unstable/linux-explicit-synchronization/linux-explicit-synchronization-unstable-v1.xml
subprojects/wayland-protocols/unstable/pointer-constraints/README
subprojects/wayland-protocols/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml
subprojects/wayland-protocols/unstable/pointer-gestures/README
subprojects/wayland-protocols/unstable/pointer-gestures/pointer-gestures-unstable-v1.xml
subprojects/wayland-protocols/unstable/primary-selection/README
subprojects/wayland-protocols/unstable/primary-selection/primary-selection-unstable-v1.xml
subprojects/wayland-protocols/unstable/relative-pointer/README
subprojects/wayland-protocols/unstable/relative-pointer/relative-pointer-unstable-v1.xml
subprojects/wayland-protocols/unstable/tablet/README
subprojects/wayland-protocols/unstable/tablet/tablet-unstable-v1.xml
subprojects/wayland-protocols/unstable/tablet/tablet-unstable-v2.xml
subprojects/wayland-protocols/unstable/text-input/README
subprojects/wayland-protocols/unstable/text-input/text-input-unstable-v1.xml
subprojects/wayland-protocols/unstable/text-input/text-input-unstable-v3.xml
subprojects/wayland-protocols/unstable/xdg-decoration/README
subprojects/wayland-protocols/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
subprojects/wayland-protocols/unstable/xdg-foreign/README
subprojects/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v1.xml
subprojects/wayland-protocols/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml
subprojects/wayland-protocols/unstable/xdg-output/README
subprojects/wayland-protocols/unstable/xdg-output/xdg-output-unstable-v1.xml
subprojects/wayland-protocols/unstable/xdg-shell/README
subprojects/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v5.xml
subprojects/wayland-protocols/unstable/xdg-shell/xdg-shell-unstable-v6.xml
subprojects/wayland-protocols/unstable/xwayland-keyboard-grab/README
subprojects/wayland-protocols/unstable/xwayland-keyboard-grab/xwayland-keyboard-grab-unstable-v1.xml
subprojects/wayland-protocols/wayland-protocols-uninstalled.pc.in
subprojects/wayland-protocols/wayland-protocols.pc.in
subprojects/wayland/.editorconfig
subprojects/wayland/.gitignore
subprojects/wayland/.gitlab-ci.yml
subprojects/wayland/.gitlab/issue_templates/Bug.md
subprojects/wayland/CONTRIBUTING.md
subprojects/wayland/COPYING
subprojects/wayland/README
subprojects/wayland/cursor/convert_font.c
subprojects/wayland/cursor/cursor-data.h
subprojects/wayland/cursor/cursor.pcf
subprojects/wayland/cursor/meson.build
subprojects/wayland/cursor/os-compatibility.c
subprojects/wayland/cursor/os-compatibility.h
subprojects/wayland/cursor/wayland-cursor.c
subprojects/wayland/cursor/wayland-cursor.h
subprojects/wayland/cursor/xcursor.c
subprojects/wayland/cursor/xcursor.h
subprojects/wayland/doc/doxygen/.gitignore
subprojects/wayland/doc/doxygen/dot/wayland-architecture.gv
subprojects/wayland/doc/doxygen/dot/x-architecture.gv
subprojects/wayland/doc/doxygen/gen-doxygen.py
subprojects/wayland/doc/doxygen/mainpage.dox
subprojects/wayland/doc/doxygen/meson.build
subprojects/wayland/doc/doxygen/wayland.doxygen.in
subprojects/wayland/doc/doxygen/xml/Client/meson.build
subprojects/wayland/doc/doxygen/xml/Server/meson.build
subprojects/wayland/doc/doxygen/xml/meson.build
subprojects/wayland/doc/meson.build
subprojects/wayland/doc/publican/.gitignore
subprojects/wayland/doc/publican/doxygen-to-publican.xsl
subprojects/wayland/doc/publican/merge-mapcoords.xsl
subprojects/wayland/doc/publican/meson.build
subprojects/wayland/doc/publican/protocol-interfaces-to-docbook.xsl
subprojects/wayland/doc/publican/protocol-to-docbook.xsl
subprojects/wayland/doc/publican/sources/Architecture.xml
subprojects/wayland/doc/publican/sources/Author_Group.xml
subprojects/wayland/doc/publican/sources/Book_Info.xml
subprojects/wayland/doc/publican/sources/Client.xml
subprojects/wayland/doc/publican/sources/Compositors.xml
subprojects/wayland/doc/publican/sources/Foreword.xml
subprojects/wayland/doc/publican/sources/Introduction.xml
subprojects/wayland/doc/publican/sources/Preface.xml
subprojects/wayland/doc/publican/sources/Protocol.xml
subprojects/wayland/doc/publican/sources/Revision_History.xml
subprojects/wayland/doc/publican/sources/Server.xml
subprojects/wayland/doc/publican/sources/Wayland.ent
subprojects/wayland/doc/publican/sources/Wayland.xml
subprojects/wayland/doc/publican/sources/Xwayland.xml
subprojects/wayland/doc/publican/sources/css/brand.css
subprojects/wayland/doc/publican/sources/css/common.css
subprojects/wayland/doc/publican/sources/css/default.css
subprojects/wayland/doc/publican/sources/css/epub.css
subprojects/wayland/doc/publican/sources/css/print.css
subprojects/wayland/doc/publican/sources/images/icon.svg
subprojects/wayland/doc/publican/sources/images/wayland.png
subprojects/wayland/doc/publican/sources/images/xwayland-architecture.png
subprojects/wayland/doc/publican/sources/meson.build
subprojects/wayland/egl/meson.build
subprojects/wayland/egl/wayland-egl-abi-check.c
subprojects/wayland/egl/wayland-egl-backend.h
subprojects/wayland/egl/wayland-egl-core.h
subprojects/wayland/egl/wayland-egl-symbols-check
subprojects/wayland/egl/wayland-egl.c
subprojects/wayland/egl/wayland-egl.h
subprojects/wayland/meson.build
subprojects/wayland/meson_options.txt
subprojects/wayland/protocol/.gitignore
subprojects/wayland/protocol/generate-shm-formats.py
subprojects/wayland/protocol/tests.xml
subprojects/wayland/protocol/wayland.dtd
subprojects/wayland/protocol/wayland.xml
subprojects/wayland/release.sh
subprojects/wayland/releasing.txt
subprojects/wayland/src/.gitignore
subprojects/wayland/src/connection.c
subprojects/wayland/src/embed.py
subprojects/wayland/src/event-loop.c
subprojects/wayland/src/meson.build
subprojects/wayland/src/scanner.c
subprojects/wayland/src/wayland-client-core.h
subprojects/wayland/src/wayland-client.c
subprojects/wayland/src/wayland-client.h
subprojects/wayland/src/wayland-os.c
subprojects/wayland/src/wayland-os.h
subprojects/wayland/src/wayland-private.h
subprojects/wayland/src/wayland-server-core.h
subprojects/wayland/src/wayland-server-private.h
subprojects/wayland/src/wayland-server.c
subprojects/wayland/src/wayland-server.h
subprojects/wayland/src/wayland-shm.c
subprojects/wayland/src/wayland-util.c
subprojects/wayland/src/wayland-util.h
subprojects/wayland/src/wayland-version.h.in
subprojects/wayland/tests/array-test.c
subprojects/wayland/tests/client-test.c
subprojects/wayland/tests/compositor-introspection-test.c
subprojects/wayland/tests/connection-test.c
subprojects/wayland/tests/cpp-compile-test.cpp
subprojects/wayland/tests/data/bad-identifier-arg.xml
subprojects/wayland/tests/data/bad-identifier-entry.xml
subprojects/wayland/tests/data/bad-identifier-enum.xml
subprojects/wayland/tests/data/bad-identifier-event.xml
subprojects/wayland/tests/data/bad-identifier-interface.xml
subprojects/wayland/tests/data/bad-identifier-protocol.xml
subprojects/wayland/tests/data/bad-identifier-request.xml
subprojects/wayland/tests/data/example-client.h
subprojects/wayland/tests/data/example-code.c
subprojects/wayland/tests/data/example-server.h
subprojects/wayland/tests/data/example.xml
subprojects/wayland/tests/data/small-client-core.h
subprojects/wayland/tests/data/small-client.h
subprojects/wayland/tests/data/small-code-core.c
subprojects/wayland/tests/data/small-code.c
subprojects/wayland/tests/data/small-private-code.c
subprojects/wayland/tests/data/small-server-core.h
subprojects/wayland/tests/data/small-server.h
subprojects/wayland/tests/data/small.xml
subprojects/wayland/tests/display-test.c
subprojects/wayland/tests/event-loop-test.c
subprojects/wayland/tests/exec-fd-leak-checker.c
subprojects/wayland/tests/fixed-benchmark.c
subprojects/wayland/tests/fixed-test.c
subprojects/wayland/tests/headers-protocol-core-test.c
subprojects/wayland/tests/headers-protocol-test.c
subprojects/wayland/tests/headers-test.c
subprojects/wayland/tests/interface-test.c
subprojects/wayland/tests/list-test.c
subprojects/wayland/tests/map-test.c
subprojects/wayland/tests/meson.build
subprojects/wayland/tests/message-test.c
subprojects/wayland/tests/newsignal-test.c
subprojects/wayland/tests/os-wrappers-test.c
subprojects/wayland/tests/protocol-logger-test.c
subprojects/wayland/tests/proxy-test.c
subprojects/wayland/tests/queue-test.c
subprojects/wayland/tests/resources-test.c
subprojects/wayland/tests/sanity-test.c
subprojects/wayland/tests/scanner-test.sh
subprojects/wayland/tests/signal-test.c
subprojects/wayland/tests/socket-test.c
subprojects/wayland/tests/test-compositor.c
subprojects/wayland/tests/test-compositor.h
subprojects/wayland/tests/test-helpers.c
subprojects/wayland/tests/test-runner.c
subprojects/wayland/tests/test-runner.h
subprojects/wayland/wayland-scanner.m4
subprojects/wayland/wayland-scanner.mk

index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7e0c0a0fc72a73d75e622d33e22b98f63c89a631
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++root = true
++
++[*.xml]
++indent_style = space
++indent_size = 2
++tab_width = 8
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cff93c80952d8f08a96d1750e27688e9db047e47
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++.templates_sha: &template_sha 290b79e0e78eab67a83766f4e9691be554fc4afd
++
++include:
++  - project: 'freedesktop/ci-templates'
++    ref: *template_sha
++    file: '/templates/debian.yml'
++  - project: 'freedesktop/ci-templates'
++    ref: *template_sha
++    file: '/templates/ci-fairy.yml'
++
++stages:
++  - review
++  - containers-build
++  - test
++
++variables:
++  FDO_UPSTREAM_REPO: wayland/wayland-protocols
++
++.debian:
++  variables:
++    FDO_DISTRIBUTION_VERSION: bullseye
++    FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config meson git ca-certificates libffi-dev libexpat1-dev libxml2-dev'
++    FDO_DISTRIBUTION_TAG: '2022-01-19.0'
++    FDO_DISTRIBUTION_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} ./.gitlab-ci/debian-install.sh'
++
++check-commit:
++  extends:
++    - .fdo.ci-fairy
++  stage: review
++  script:
++    - ci-fairy check-commits --signed-off-by --junit-xml=results.xml
++  variables:
++    GIT_DEPTH: 100
++  artifacts:
++    reports:
++      junit: results.xml
++
++container_build:
++  extends:
++    - .debian
++    - .fdo.container-build@debian
++  stage: containers-build
++  variables:
++    GIT_STRATEGY: none
++
++test-meson:
++  stage: test
++  extends:
++    - .debian
++    - .fdo.distribution-image@debian
++  script:
++    - meson build
++    - ninja -C build
++    - meson test -C build
++    - ninja -C build install
++  artifacts:
++    name: wayland-protocols-$CI_COMMIT_SHA
++    when: always
++    paths:
++    - $CI_PROJECT_DIR/build/meson-logs
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..256d665bc15c6621b277615513bd56741dfd23d0
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++#!/bin/sh -eux
++
++# Note: don't forget to bump FDO_DISTRIBUTION_TAG when editing this file!
++
++git clone --branch 1.20.0 --depth=1 https://gitlab.freedesktop.org/wayland/wayland
++cd wayland/
++git show -s HEAD
++meson build/ -Dtests=false -Ddocumentation=false
++ninja -j${FDO_CI_CONCURRENT:-4} -C build/ install
++cd ..
++rm -rf wayland/
++
++echo "/usr/local/lib" >/etc/ld.so.conf.d/local.conf
++ldconfig
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8ab3291e38567bf638567900ccf84fc1330c1cd9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,33 @@@
++Copyright © 2008-2013 Kristian Høgsberg
++Copyright © 2010-2013 Intel Corporation
++Copyright © 2013      Rafael Antognolli
++Copyright © 2013      Jasper St. Pierre
++Copyright © 2014      Jonas Ådahl
++Copyright © 2014      Jason Ekstrand
++Copyright © 2014-2015 Collabora, Ltd.
++Copyright © 2015      Red Hat Inc.
++
++Permission is hereby granted, free of charge, to any person obtaining a
++copy of this software and associated documentation files (the "Software"),
++to deal in the Software without restriction, including without limitation
++the rights to use, copy, modify, merge, publish, distribute, sublicense,
++and/or sell copies of the Software, and to permit persons to whom the
++Software is furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice (including the next
++paragraph) shall be included in all copies or substantial portions of the
++Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++
++---
++
++The above is the version of the MIT "Expat" License used by X.org:
++
++    http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..76606dbb34e9899c44eaa5817798917af384a9a4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,149 @@@
++# wayland-protocols governance
++
++This document governs the maintenance of wayland-protocols and serves to outline
++the broader process for standardization of protocol extensions in the Wayland
++ecosystem.
++
++## 1. Membership
++
++Membership in wayland-protocols is offered to stakeholders in the Wayland
++ecosystem who have an interest in participating in protocol extension
++standardization.
++
++### 1.1. Membership requirements
++
++1. Membership is extended to projects, rather than individuals.
++2. Members represent general-purpose projects with a stake in multiple Wayland
++   protocols (e.g. compositors, GUI toolkits, etc), rather than special-purpose
++   applications with a stake in only one or two.
++3. Each project must provide one or two named individuals as points-of-contact
++   for that project who can be reached to discuss protocol-related matters.
++4. During a vote, if two points-of-contact for the same member disagree, the
++   member's vote is considered blank.
++
++### 1.2. Becoming a member
++
++1. New members who meet the criteria outlined in 1.1 are established by
++   invitation from an existing member. Projects hoping to join should reach out
++   to an existing member asking for this invitation.
++2. New members shall write to the wayland-devel mailing list stating their
++   intention of joining and their sponsor.
++3. The sponsor shall respond acknowledging their sponsorship of the membership.
++4. A 14 day discussion period for comments from wayland-protocols members will
++   be held.
++5. At the conclusion of the discussion period, the new membership is established
++   unless their application was NACKed by a 1/2 majority of all existing members.
++
++### 1.3. Ceasing membership
++
++1. A member may step down by writing their intention to do so to the
++   wayland-devel mailing list.
++2. A removal vote may be called for by an existing member by posting to the
++   wayland-devel mailing list. This begins a 14 day voting & discussion
++   period.
++3. At the conclusion of the voting period, the member is removed if the votes
++   total 2/3rds of all current members.
++4. Removed members are not eligible to apply for membership again for a period
++   of 1 year.
++5. Following a failed vote, the member who called for the vote cannot
++   call for a re-vote or propose any other removal for 90 days.
++
++## 2. Protocols
++
++### 2.1. Protocol namespaces
++
++1. Namespaces are implemented in practice by prefixing each interface name in a
++   protocol definition (XML) with the namespace name, and an underscore (e.g.
++   "xdg_wm_base").
++2. Protocols in a namespace may optionally use the namespace followed by a dash
++   in the name (e.g. "xdg-shell").
++3. The "xdg" namespace is established for protocols letting clients
++   configure its surfaces as "windows", allowing clients to affect how they
++   are managed.
++4. The "wp" namespace is established for protocols generally useful to Wayland
++   implementations (i.e. "plumbing" protocols).
++5. The "ext" namespace is established as a general catch-all for protocols that
++   fit into no other namespace.
++
++### 2.2. Protocol inclusion requirements
++
++1. All protocols found in the "xdg" and "wp" namespaces at the time of writing
++   are grandfathered into their respective namespace without further discussion.
++2. Protocols in the "xdg" and "wp" namespace are eligible for inclusion only if
++   ACKed by at least 3 members.
++3. Protocols in the "xdg" and "wp" namespace are ineligible for inclusion if
++   if NACKed by any member.
++4. Protocols in the "xdg" and "wp" namespaces must have at least 3 open-source
++   implementations (either 1 client + 2 servers, or 2 clients + 1 server) to be
++   eligible for inclusion.
++5. Protocols in the "ext" namespace are eligible for inclusion only if ACKed by
++   at least one other member.
++6. Protocols in the "ext" namespace must have at least one open-source client &
++   one open-source server implementation to be eligible for inclusion.
++7. "Open-source" is defined as distributed with an Open Source Initiative
++   approved license.
++
++### 2.3. Introducing new protocols
++
++1. A new protocol may be proposed by submitting a merge request to the
++   wayland-protocols Gitlab repository.
++2. Protocol proposal posts must include justification for their inclusion in
++   their namespace per the requirements outlined in section 2.2.
++3. An indefinite discussion period for comments from wayland-protocols members
++   will be held, with a minimum duration of 30 days. Protocols which require a
++   certain level of implementation status, ACKs from members, and so on, should
++   use this time to acquire them.
++4. When the proposed protocol meets all requirements for inclusion per section
++   2.2, and the minimum discussion period has elapsed, the sponsoring member may
++   merge their changes in the wayland-protocol repository.
++5. Amendments to existing protocols may be proposed by the same process, with
++   no minimum discussion period.
++6. Declaring a protocol stable may be proposed by the same process, with the
++   regular 30 day minimum discussion period.
++
++## 3. Protocol adoption documentation
++
++### 3.1. Adoption website
++
++1. This section is informational.
++2. A website will be made available for interested parties to browse the
++   implementation status of protocols included in wayland-protocols.
++3. A statement from each member of wayland-protocols will be included on the
++   site.
++4. Each protocol will be listed along with its approval status from each member.
++5. The approval statuses are:
++   1. NACK, or "negative acknowledgement", meaning that the member is opposed to
++      the protocol in principle.
++   2. NOPP, or "no opposition", meaning that the member is not opposed to the
++      protocol in principle, but does not provide an implementation.
++   3. ACK, or "acknowledged", meaning that the member supports the protocol in
++      principle, but does not provide an implementation.
++   4. IMPL, or "implemented", meaning that the member supports the protocol and
++      provides an implementation.
++6. Each member may write a short statement expanding on the rationale for their
++   approval status, which will be included on the site.
++7. A supplementary list of implementations will also be provided on the site,
++   which may include implementations supported by non-members.
++
++### 3.2. Changes to the adoption website
++
++1. This section is informational.
++2. A new protocol is added to the website by the sponsoring member at the
++   conclusion of the discussion period (section 2.3.3).
++3. During the discussion period (section 2.3.3), interested parties may express
++   their approval status on the Gitlab merge request. The default approval
++   status for members who do not participate in the discussion is "NOPP".
++4. Members may change their acknowledgement status or support statement at any
++   time after the discussion period (section 2.3.3) has closed by simply merging
++   their update in the wayland-protocols repository.
++
++## 4. Amending this document
++
++1. An amendment to this document may be proposed any member by
++   submitting a merge request on Gitlab.
++2. A 30 day discussion period for comments from wayland-protocols members will
++   be held.
++3. At the conclusion of the discussion period, an amendment will become
++   effective if it's ACKed by at least 2/3rds of all wayland-protocols members,
++   and NACKed by none. The sponsoring member may merge their change to the
++   wayland-protocols repository at this point.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..35ebbc68583d8a3a7346c73d6644ba25524885eb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++# wayland-protocols members
++
++- EFL/Enlightenment: Mike Blumenkrantz <michael.blumenkrantz@gmail.com> (@zmike)
++- GTK/Mutter: Jonas Ådahl <jadahl@gmail.com> (@jadahl),
++  Carlos Garnacho <carlosg@gnome.org> (@carlosg)
++- KWin: Vlad Zahorodnii <vlad.zahorodnii@kde.org> (@zzag),
++  David Edmundson <david@davidedmundson.co.uk> (@davidedmundson)
++- Mir: Christopher James Halse Rogers <raof@ubuntu.com> (@RAOF),
++  Alan Griffiths <alan.griffiths@canonical.com>
++- Qt: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
++  (@eskilblomfeldt)
++- Weston: Pekka Paalanen <pekka.paalanen@collabora.com> (@pq),
++  Daniel Stone <daniel@fooishbar.org> (@daniels)
++- wlroots/Sway: Simon Ser <contact@emersion.fr> (@emersion),
++  Simon Zeni <simon@bl4ckb0ne.ca> (@bl4ckb0ne)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f88716f7f6414c13fbf3510f55259d27c1582012
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,259 @@@
++# Wayland protocols
++
++wayland-protocols contains Wayland protocols that add functionality not
++available in the Wayland core protocol. Such protocols either add
++completely new functionality, or extend the functionality of some other
++protocol either in Wayland core, or some other protocol in
++wayland-protocols.
++
++A protocol in wayland-protocols consists of a directory containing a set
++of XML files containing the protocol specification, and a README file
++containing detailed state and a list of maintainers.
++
++## Protocol phases
++
++Protocols in general has three phases: the development phase, the testing
++phase, and the stable phase.
++
++In the development phase, a protocol is not officially part of
++wayland-protocols, but is actively being developed, for example by
++iterating over it in a
++[merge
++request](https://gitlab.freedesktop.org/wayland/wayland-protocols/merge_requests),
++or planning it in an
++[issue](https://gitlab.freedesktop.org/wayland/wayland-protocols/issues).
++
++During this phase, patches for clients and compositors are written as a test
++vehicle. Such patches must not be merged in clients and compositors, because
++the protocol can still change.
++
++When a protocol has reached a stage where it is ready for wider adoption,
++and after the [GOVERNANCE section
++2.3](GOVERNANCE.md#2.3-introducing-new-protocols) requirements have been
++met, it enters the "testing" phase. At this point, the protocol is added
++to `staging/` directory of wayland-protocols and made part of a release.
++What this means is that implementation is encouraged in clients and
++compositors where the functionality it specifies is wanted.
++
++Extensions in staging cannot have backward incompatible changes, in that
++sense they are equal to stable extensions. However, they may be completely
++replaced with a new major version, or a different protocol extension all
++together, if design flaws are found in the testing phase.
++
++After a staging protocol has been sufficiently tested in the wild and
++proven adequate, its maintainers and the community at large may declare it
++"stable", meaning it is unexpected to become superseded by a new major
++version.
++
++## Deprecation
++
++A protocol may be deprecated, if it has been replaced by some other
++protocol, or declared undesirable for some other reason. No more changes
++will be made to a deprecated protocol.
++
++## Legacy protocol phases
++
++An "unstable" protocol refers to a protocol categorization policy
++previously used by wayland-protocols, where protocols initially
++placed in the `unstable/` directory had certain naming conventions were
++applied, requiring a backward incompatible change to be declared "stable".
++
++During this phase, protocol extension interface names were in addition to
++the major version postfix also prefixed with `z` to distinguish from
++stable protocols.
++
++## Protocol directory tree structure
++
++Depending on which stage a protocol is in, the protocol is placed within
++the toplevel directory containing the protocols with the same stage.
++Stable protocols are placed in the `stable/` directory, staging protocols
++are placed in the `staging/` directory, and deprecated protocols are
++placed in the `deprecated/` directory.
++
++Unstable protocols (see [Legacy protocol phases](#legacy-protocol-phases))
++can be found in the `unstable/` directory, but new ones should never be
++placed here.
++
++## Protocol development procedure
++
++To propose a new protocol, create a GitLab merge request adding the
++relevant files and Makefile.am entry to the repository with the
++explanation and motivation in the commit message. Protocols are
++organized in namespaces describing their scope ("wp", "xdg" and "ext").
++There are different requirements for each namespace, see [GOVERNANCE
++section 2](GOVERNANCE.md#2-protocols) for more information.
++
++If the new protocol is just an idea, open an issue on the GitLab issue
++tracker. If the protocol isn't ready for complete review yet and is an
++RFC, create a merge request and add the "WIP:" prefix in the title.
++
++To propose changes to existing protocols, create a GitLab merge request.
++
++Please include a `Signed-off-by` line at the end of the commit to certify
++that you wrote it or otherwise have the right to pass it on as an
++open-source patch. See the
++[Developer Certificate of Origin](https://developercertificate.org/) for
++a formal definition.
++
++## Interface naming convention
++
++All protocols should avoid using generic namespaces or no namespaces in
++the protocol interface names in order to minimize risk that the generated
++C API collides with other C API. Interface names that may collide with
++interface names from other protocols should also be avoided.
++
++For generic protocols not limited to certain configurations (such as
++specific desktop environment or operating system) the `wp_` prefix
++should be used on all interfaces in the protocol.
++
++For protocols allowing clients to configure how their windows are
++managed, the `xdg_` prefix should be used.
++
++For operating system specific protocols, the interfaces should be
++prefixed with both `wp_` and the operating system, for example
++`wp_linux_`, or `wp_freebsd_`, etc.
++
++For more information about namespaces, see [GOVERNANCE section 2.1
++](GOVERNANCE.md#21-protocol-namespaces).
++
++Each new protocol XML file must include a major version postfix, starting
++with `-v1`. The purpose of this postfix is to make it possible to
++distinguish between backward incompatible major versions of the same
++protocol.
++
++The interfaces in the protocol XML file should as well have the same
++major version postfix in their names.
++
++For example, the protocol `foo-bar` may have a XML file
++`foo-bar/foo-bar-v1.xml`, consisting of the interface `wp_foo_bar_v1`,
++corresponding to the major version 1, as well as the newer version
++`foo-bar/foo-bar-v2.xml` consisting of the interface `wp_foo_bar_v2`,
++corresponding to the major version 2.
++
++## Include a disclaimer
++
++Include the following disclaimer:
++
++```
++Warning! The protocol described in this file is currently in the testing
++phase. Backward compatible changes may be added together with the
++corresponding interface version bump. Backward incompatible changes can
++only be done by creating a new major version of the extension.
++```
++
++## Use of RFC 2119 keywords
++
++Descriptions of all new protocols must use (in lowercase) and adhere to the
++proper meaning of the keywords described in
++[RFC 2119](https://www.rfc-editor.org/info/rfc2119).
++
++All protocol descriptions that follow the guidelines in RFC 2119 must
++incorporate the following text in their toplevel protocol description section:
++
++```
++The key words "must", "must not", "required", "shall", "shall not", "should",
++"should not", "recommended",  "may", and "optional" in this document are to
++be interpreted as described in IETF RFC 2119.
++```
++
++Note that not all existing protocol descriptions conform to RFC 2119. Protocol
++maintainers are encouraged to audit their descriptions, update them as needed
++to follow RFC 2119 guidelines, and mark them as conformant in the way described
++in the previous paragraph.
++
++## Backward compatible protocol changes
++
++A protocol may receive backward compatible additions and changes. This
++is to be done in the general Wayland way, using `version` and `since` XML
++element attributes.
++
++## Backward incompatible protocol changes
++
++While not preferred, a protocol may at any stage, especially during the
++testing phase, when it is located in the `staging/` directory, see
++backward incompatible changes.
++
++Assuming a backward incompatible change is needed, the procedure for how to
++do so is the following:
++
++- Make a copy of the XML file with the major version increased by 1.
++- Increase the major version number in the protocol XML by 1.
++- Increase the major version number in all of the interfaces in the
++  XML by 1.
++- Reset the interface version number (interface version attribute) of all
++  the interfaces to 1.
++- Remove all of the `since` attributes.
++
++## Declaring a protocol stable
++
++Once it has been concluded that a protocol been proven adequate in
++production, and that it is deemed unlikely to receive any backward
++incompatible changes, it may be declared stable.
++
++The procedure of doing this is the following:
++
++- Create a new directory in the `stable/` toplevel directory with the
++  same name as the protocol directory in the `staging/` directory.
++- Copy the final version of the XML that is the version that was
++  decided to be declared stable into the new directory. The target name
++  should be the same name as the protocol directory but with the `.xml`
++  suffix.
++- Remove the disclaimer about the protocol being in the testing phase.
++- Update the `README` file in the staging directory and create a new
++  `README` file in the new directory.
++- Replace the disclaimer in the protocol files left in the staging/
++  directory with the following:
++
++```
++Disclaimer: This protocol extension has been marked stable. This copy is
++no longer used and only retained for backwards compatibility. The
++canonical version can be found in the stable/ directory.
++```
++
++Note that the major version of the stable protocol extension, as well as
++all the interface versions and names, must remain unchanged.
++
++There are other requirements for declaring a protocol stable, see
++[GOVERNANCE section 2.3](GOVERNANCE.md#23-introducing-new-protocols).
++
++## Releases
++
++Each release of wayland-protocols finalizes the version of the protocols
++to their state they had at that time.
++
++## Gitlab conventions
++
++### Triaging merge requests
++
++New merge requests should be triaged. Doing so requires the one doing the
++triage to add a set of initial labels:
++
++~"New Protocol" - For a new protocol being added. If it's an amendment to
++an existing protocol, apply the label of the corresponding protocol
++instead. If none exist, create it.
++
++~"Needs acks" - If the protocol needs one or more acknowledgements.
++
++~"Needs implementations" - If there are not enough implementations of the
++protocol.
++
++~"Needs review" - If the protocol is in need of review.
++
++~"In 30 day discussion period" - If the protocol needs a 30 day discussion
++period.
++
++For the meaning and requirement of acknowledgments and available
++implementations, see the GOVERNANCE.md document.
++
++### Managing merge requests
++
++When merge requests get their needed feedback and items, remove the
++corresponding label that marks it as needing something. For example, if a
++merge request receives all the required acknowledgments, remove the
++~"Needs acks" label, or if 30 days passed since opening, remove any
++~"In 30 day discussion period" label.
++
++### Nacking a merge request
++
++If the inclusion of a merge request is denied due to one or more Nacks, add
++the ~Nacked label.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b917ca5e2e1b4ea6fb81118729d7285a556e69ea
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,120 @@@
++project('wayland-protocols',
++      version: '1.26',
++      meson_version: '>= 0.55.0',
++      license: 'MIT/Expat',
++)
++
++wayland_protocols_version = meson.project_version()
++
++fs = import('fs')
++
++stable_protocols = [
++      'presentation-time',
++      'viewporter',
++      'xdg-shell',
++]
++
++unstable_protocols = {
++      'fullscreen-shell': ['v1'],
++      'idle-inhibit': ['v1'],
++      'input-method': ['v1'],
++      'input-timestamps': ['v1'],
++      'keyboard-shortcuts-inhibit': ['v1'],
++      'linux-dmabuf': ['v1'],
++      'linux-explicit-synchronization': ['v1'],
++      'pointer-constraints': ['v1'],
++      'pointer-gestures': ['v1'],
++      'primary-selection': ['v1'],
++      'relative-pointer': ['v1'],
++      'tablet': ['v1', 'v2'],
++      'text-input': ['v1', 'v3'],
++      'xdg-decoration': ['v1'],
++      'xdg-foreign': ['v1', 'v2'],
++      'xdg-output': ['v1'],
++      'xdg-shell': ['v5', 'v6'],
++      'xwayland-keyboard-grab': ['v1'],
++}
++
++staging_protocols = {
++      'xdg-activation': ['v1'],
++      'drm-lease': ['v1'],
++      'ext-session-lock': ['v1'],
++      'single-pixel-buffer': ['v1'],
++}
++
++protocol_files = []
++
++foreach name : stable_protocols
++      protocol_files += ['stable/@0@/@0@.xml'.format(name)]
++endforeach
++
++foreach name : staging_protocols.keys()
++      foreach version : staging_protocols.get(name)
++              protocol_files += [
++                      'staging/@0@/@0@-@1@.xml'.format(name, version)
++              ]
++      endforeach
++endforeach
++
++foreach name : unstable_protocols.keys()
++      foreach version : unstable_protocols.get(name)
++              protocol_files += [
++                      'unstable/@0@/@0@-unstable-@1@.xml'.format(name, version)
++              ]
++      endforeach
++endforeach
++
++# Check that each protocol has a README
++foreach protocol_file : protocol_files
++      dir = fs.parent(protocol_file)
++      if not fs.is_file(dir + '/README')
++              error('Missing README in @0@'.format(protocol_file))
++      endif
++endforeach
++
++foreach protocol_file : protocol_files
++      protocol_install_dir = fs.parent(join_paths(
++              get_option('datadir'),
++              'wayland-protocols',
++              protocol_file,
++      ))
++      install_data(
++              protocol_file,
++              install_dir: protocol_install_dir,
++      )
++endforeach
++
++wayland_protocols_srcdir = meson.current_source_dir()
++
++pkgconfig_configuration = configuration_data()
++pkgconfig_configuration.set('prefix', get_option('prefix'))
++pkgconfig_configuration.set('datarootdir', '${prefix}/@0@'.format(get_option('datadir')))
++pkgconfig_configuration.set('abs_top_srcdir', wayland_protocols_srcdir)
++pkgconfig_configuration.set('PACKAGE', 'wayland-protocols')
++pkgconfig_configuration.set('WAYLAND_PROTOCOLS_VERSION', wayland_protocols_version)
++
++pkg_install_dir = join_paths(get_option('datadir'), 'pkgconfig')
++configure_file(
++      input: 'wayland-protocols.pc.in',
++      output: 'wayland-protocols.pc',
++      configuration: pkgconfig_configuration,
++      install_dir: pkg_install_dir,
++)
++
++configure_file(
++      input: 'wayland-protocols-uninstalled.pc.in',
++      output: 'wayland-protocols-uninstalled.pc',
++      configuration: pkgconfig_configuration,
++)
++
++wayland_protocols = declare_dependency(
++      variables: {
++              'pkgdatadir': wayland_protocols_srcdir,
++      },
++)
++
++meson.override_dependency('wayland-protocols', wayland_protocols)
++
++if get_option('tests')
++      subdir('tests')
++endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f361d3b3c89a4042150025014ca17213e2724e8b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++option('tests',
++       type: 'boolean',
++       value: true,
++       description: 'Build the tests')
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c7781ea802fe6350ce05737aec567c7f71324e4b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++Presentation time protocol
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..04301ff32929ef7a3927257dfeb905b137863525
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,266 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="presentation_time">
++<!-- wrap:70 -->
++
++  <copyright>
++    Copyright © 2013-2014 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="wp_presentation" version="1">
++    <description summary="timed presentation related wl_surface requests">
++
++<!-- Introduction -->
++
++      The main feature of this interface is accurate presentation
++      timing feedback to ensure smooth video playback while maintaining
++      audio/video synchronization. Some features use the concept of a
++      presentation clock, which is defined in the
++      presentation.clock_id event.
++
++      A content update for a wl_surface is submitted by a
++      wl_surface.commit request. Request 'feedback' associates with
++      the wl_surface.commit and provides feedback on the content
++      update, particularly the final realized presentation time.
++
++<!-- Completing presentation -->
++
++      When the final realized presentation time is available, e.g.
++      after a framebuffer flip completes, the requested
++      presentation_feedback.presented events are sent. The final
++      presentation time can differ from the compositor's predicted
++      display update time and the update's target time, especially
++      when the compositor misses its target vertical blanking period.
++    </description>
++
++    <enum name="error">
++      <description summary="fatal presentation errors">
++        These fatal protocol errors may be emitted in response to
++        illegal presentation requests.
++      </description>
++      <entry name="invalid_timestamp" value="0"
++             summary="invalid value in tv_nsec"/>
++      <entry name="invalid_flag" value="1"
++             summary="invalid flag"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="unbind from the presentation interface">
++        Informs the server that the client will no longer be using
++        this protocol object. Existing objects created by this object
++        are not affected.
++      </description>
++    </request>
++
++    <request name="feedback">
++      <description summary="request presentation feedback information">
++        Request presentation feedback for the current content submission
++        on the given surface. This creates a new presentation_feedback
++        object, which will deliver the feedback information once. If
++        multiple presentation_feedback objects are created for the same
++        submission, they will all deliver the same information.
++
++        For details on what information is returned, see the
++        presentation_feedback interface.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"
++           summary="target surface"/>
++      <arg name="callback" type="new_id" interface="wp_presentation_feedback"
++           summary="new feedback object"/>
++    </request>
++
++    <event name="clock_id">
++      <description summary="clock ID for timestamps">
++        This event tells the client in which clock domain the
++        compositor interprets the timestamps used by the presentation
++        extension. This clock is called the presentation clock.
++
++        The compositor sends this event when the client binds to the
++        presentation interface. The presentation clock does not change
++        during the lifetime of the client connection.
++
++        The clock identifier is platform dependent. On Linux/glibc,
++        the identifier value is one of the clockid_t values accepted
++        by clock_gettime(). clock_gettime() is defined by
++        POSIX.1-2001.
++
++        Timestamps in this clock domain are expressed as tv_sec_hi,
++        tv_sec_lo, tv_nsec triples, each component being an unsigned
++        32-bit value. Whole seconds are in tv_sec which is a 64-bit
++        value combined from tv_sec_hi and tv_sec_lo, and the
++        additional fractional part in tv_nsec as nanoseconds. Hence,
++        for valid timestamps tv_nsec must be in [0, 999999999].
++
++        Note that clock_id applies only to the presentation clock,
++        and implies nothing about e.g. the timestamps used in the
++        Wayland core protocol input events.
++
++        Compositors should prefer a clock which does not jump and is
++        not slewed e.g. by NTP. The absolute value of the clock is
++        irrelevant. Precision of one millisecond or better is
++        recommended. Clients must be able to query the current clock
++        value directly, not by asking the compositor.
++      </description>
++      <arg name="clk_id" type="uint" summary="platform clock identifier"/>
++    </event>
++
++  </interface>
++
++  <interface name="wp_presentation_feedback" version="1">
++    <description summary="presentation time feedback event">
++      A presentation_feedback object returns an indication that a
++      wl_surface content update has become visible to the user.
++      One object corresponds to one content update submission
++      (wl_surface.commit). There are two possible outcomes: the
++      content update is presented to the user, and a presentation
++      timestamp delivered; or, the user did not see the content
++      update because it was superseded or its surface destroyed,
++      and the content update is discarded.
++
++      Once a presentation_feedback object has delivered a 'presented'
++      or 'discarded' event it is automatically destroyed.
++    </description>
++
++    <event name="sync_output">
++      <description summary="presentation synchronized to this output">
++        As presentation can be synchronized to only one output at a
++        time, this event tells which output it was. This event is only
++        sent prior to the presented event.
++
++        As clients may bind to the same global wl_output multiple
++        times, this event is sent for each bound instance that matches
++        the synchronized output. If a client has not bound to the
++        right wl_output global at all, this event is not sent.
++      </description>
++      <arg name="output" type="object" interface="wl_output"
++           summary="presentation output"/>
++    </event>
++
++    <enum name="kind" bitfield="true">
++      <description summary="bitmask of flags in presented event">
++        These flags provide information about how the presentation of
++        the related content update was done. The intent is to help
++        clients assess the reliability of the feedback and the visual
++        quality with respect to possible tearing and timings.
++      </description>
++      <entry name="vsync" value="0x1">
++        <description summary="presentation was vsync'd">
++          The presentation was synchronized to the "vertical retrace" by
++          the display hardware such that tearing does not happen.
++          Relying on software scheduling is not acceptable for this
++          flag. If presentation is done by a copy to the active
++          frontbuffer, then it must guarantee that tearing cannot
++          happen.
++        </description>
++      </entry>
++      <entry name="hw_clock" value="0x2">
++        <description summary="hardware provided the presentation timestamp">
++          The display hardware provided measurements that the hardware
++          driver converted into a presentation timestamp. Sampling a
++          clock in software is not acceptable for this flag.
++        </description>
++      </entry>
++      <entry name="hw_completion" value="0x4">
++        <description summary="hardware signalled the start of the presentation">
++          The display hardware signalled that it started using the new
++          image content. The opposite of this is e.g. a timer being used
++          to guess when the display hardware has switched to the new
++          image content.
++        </description>
++      </entry>
++      <entry name="zero_copy" value="0x8">
++        <description summary="presentation was done zero-copy">
++          The presentation of this update was done zero-copy. This means
++          the buffer from the client was given to display hardware as
++          is, without copying it. Compositing with OpenGL counts as
++          copying, even if textured directly from the client buffer.
++          Possible zero-copy cases include direct scanout of a
++          fullscreen surface and a surface on a hardware overlay.
++        </description>
++      </entry>
++    </enum>
++
++    <event name="presented" type="destructor">
++      <description summary="the content update was displayed">
++        The associated content update was displayed to the user at the
++        indicated time (tv_sec_hi/lo, tv_nsec). For the interpretation of
++        the timestamp, see presentation.clock_id event.
++
++        The timestamp corresponds to the time when the content update
++        turned into light the first time on the surface's main output.
++        Compositors may approximate this from the framebuffer flip
++        completion events from the system, and the latency of the
++        physical display path if known.
++
++        This event is preceded by all related sync_output events
++        telling which output's refresh cycle the feedback corresponds
++        to, i.e. the main output for the surface. Compositors are
++        recommended to choose the output containing the largest part
++        of the wl_surface, or keeping the output they previously
++        chose. Having a stable presentation output association helps
++        clients predict future output refreshes (vblank).
++
++        The 'refresh' argument gives the compositor's prediction of how
++        many nanoseconds after tv_sec, tv_nsec the very next output
++        refresh may occur. This is to further aid clients in
++        predicting future refreshes, i.e., estimating the timestamps
++        targeting the next few vblanks. If such prediction cannot
++        usefully be done, the argument is zero.
++
++        If the output does not have a constant refresh rate, explicit
++        video mode switches excluded, then the refresh argument must
++        be zero.
++
++        The 64-bit value combined from seq_hi and seq_lo is the value
++        of the output's vertical retrace counter when the content
++        update was first scanned out to the display. This value must
++        be compatible with the definition of MSC in
++        GLX_OML_sync_control specification. Note, that if the display
++        path has a non-zero latency, the time instant specified by
++        this counter may differ from the timestamp's.
++
++        If the output does not have a concept of vertical retrace or a
++        refresh cycle, or the output device is self-refreshing without
++        a way to query the refresh count, then the arguments seq_hi
++        and seq_lo must be zero.
++      </description>
++      <arg name="tv_sec_hi" type="uint"
++           summary="high 32 bits of the seconds part of the presentation timestamp"/>
++      <arg name="tv_sec_lo" type="uint"
++           summary="low 32 bits of the seconds part of the presentation timestamp"/>
++      <arg name="tv_nsec" type="uint"
++           summary="nanoseconds part of the presentation timestamp"/>
++      <arg name="refresh" type="uint" summary="nanoseconds till next refresh"/>
++      <arg name="seq_hi" type="uint"
++           summary="high 32 bits of refresh counter"/>
++      <arg name="seq_lo" type="uint"
++           summary="low 32 bits of refresh counter"/>
++      <arg name="flags" type="uint" enum="kind" summary="combination of 'kind' values"/>
++    </event>
++
++    <event name="discarded" type="destructor">
++      <description summary="the content update was not displayed">
++        The content update was never displayed to the user.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e09057b16cb7c842cb1a8006e2785cc9826afe0a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++Viewporter: cropping and scaling extension for surface contents
++
++Previously known as wl_scaler.
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d1048d1f3327603af92ceaa446843f8fc354f819
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,180 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="viewporter">
++
++  <copyright>
++    Copyright © 2013-2016 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="wp_viewporter" version="1">
++    <description summary="surface cropping and scaling">
++      The global interface exposing surface cropping and scaling
++      capabilities is used to instantiate an interface extension for a
++      wl_surface object. This extended interface will then allow
++      cropping and scaling the surface contents, effectively
++      disconnecting the direct relationship between the buffer and the
++      surface size.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unbind from the cropping and scaling interface">
++      Informs the server that the client will not be using this
++      protocol object anymore. This does not affect any other objects,
++      wp_viewport objects included.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="viewport_exists" value="0"
++             summary="the surface already has a viewport object associated"/>
++    </enum>
++
++    <request name="get_viewport">
++      <description summary="extend surface interface for crop and scale">
++      Instantiate an interface extension for the given wl_surface to
++      crop and scale its content. If the given wl_surface already has
++      a wp_viewport object associated, the viewport_exists
++      protocol error is raised.
++      </description>
++      <arg name="id" type="new_id" interface="wp_viewport"
++           summary="the new viewport interface id"/>
++      <arg name="surface" type="object" interface="wl_surface"
++           summary="the surface"/>
++    </request>
++  </interface>
++
++  <interface name="wp_viewport" version="1">
++    <description summary="crop and scale interface to a wl_surface">
++      An additional interface to a wl_surface object, which allows the
++      client to specify the cropping and scaling of the surface
++      contents.
++
++      This interface works with two concepts: the source rectangle (src_x,
++      src_y, src_width, src_height), and the destination size (dst_width,
++      dst_height). The contents of the source rectangle are scaled to the
++      destination size, and content outside the source rectangle is ignored.
++      This state is double-buffered, and is applied on the next
++      wl_surface.commit.
++
++      The two parts of crop and scale state are independent: the source
++      rectangle, and the destination size. Initially both are unset, that
++      is, no scaling is applied. The whole of the current wl_buffer is
++      used as the source, and the surface size is as defined in
++      wl_surface.attach.
++
++      If the destination size is set, it causes the surface size to become
++      dst_width, dst_height. The source (rectangle) is scaled to exactly
++      this size. This overrides whatever the attached wl_buffer size is,
++      unless the wl_buffer is NULL. If the wl_buffer is NULL, the surface
++      has no content and therefore no size. Otherwise, the size is always
++      at least 1x1 in surface local coordinates.
++
++      If the source rectangle is set, it defines what area of the wl_buffer is
++      taken as the source. If the source rectangle is set and the destination
++      size is not set, then src_width and src_height must be integers, and the
++      surface size becomes the source rectangle size. This results in cropping
++      without scaling. If src_width or src_height are not integers and
++      destination size is not set, the bad_size protocol error is raised when
++      the surface state is applied.
++
++      The coordinate transformations from buffer pixel coordinates up to
++      the surface-local coordinates happen in the following order:
++        1. buffer_transform (wl_surface.set_buffer_transform)
++        2. buffer_scale (wl_surface.set_buffer_scale)
++        3. crop and scale (wp_viewport.set*)
++      This means, that the source rectangle coordinates of crop and scale
++      are given in the coordinates after the buffer transform and scale,
++      i.e. in the coordinates that would be the surface-local coordinates
++      if the crop and scale was not applied.
++
++      If src_x or src_y are negative, the bad_value protocol error is raised.
++      Otherwise, if the source rectangle is partially or completely outside of
++      the non-NULL wl_buffer, then the out_of_buffer protocol error is raised
++      when the surface state is applied. A NULL wl_buffer does not raise the
++      out_of_buffer error.
++
++      If the wl_surface associated with the wp_viewport is destroyed,
++      all wp_viewport requests except 'destroy' raise the protocol error
++      no_surface.
++
++      If the wp_viewport object is destroyed, the crop and scale
++      state is removed from the wl_surface. The change will be applied
++      on the next wl_surface.commit.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove scaling and cropping from the surface">
++      The associated wl_surface's crop and scale state is removed.
++      The change is applied on the next wl_surface.commit.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="bad_value" value="0"
++           summary="negative or zero values in width or height"/>
++      <entry name="bad_size" value="1"
++           summary="destination size is not integer"/>
++      <entry name="out_of_buffer" value="2"
++           summary="source rectangle extends outside of the content area"/>
++      <entry name="no_surface" value="3"
++           summary="the wl_surface was destroyed"/>
++    </enum>
++
++    <request name="set_source">
++      <description summary="set the source rectangle for cropping">
++      Set the source rectangle of the associated wl_surface. See
++      wp_viewport for the description, and relation to the wl_buffer
++      size.
++
++      If all of x, y, width and height are -1.0, the source rectangle is
++      unset instead. Any other set of values where width or height are zero
++      or negative, or x or y are negative, raise the bad_value protocol
++      error.
++
++      The crop and scale state is double-buffered state, and will be
++      applied on the next wl_surface.commit.
++      </description>
++      <arg name="x" type="fixed" summary="source rectangle x"/>
++      <arg name="y" type="fixed" summary="source rectangle y"/>
++      <arg name="width" type="fixed" summary="source rectangle width"/>
++      <arg name="height" type="fixed" summary="source rectangle height"/>
++    </request>
++
++    <request name="set_destination">
++      <description summary="set the surface size for scaling">
++      Set the destination size of the associated wl_surface. See
++      wp_viewport for the description, and relation to the wl_buffer
++      size.
++
++      If width is -1 and height is -1, the destination size is unset
++      instead. Any other pair of values for width and height that
++      contains zero or negative values raises the bad_value protocol
++      error.
++
++      The crop and scale state is double-buffered state, and will be
++      applied on the next wl_surface.commit.
++      </description>
++      <arg name="width" type="int" summary="surface width"/>
++      <arg name="height" type="int" summary="surface height"/>
++    </request>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c45f70c8300a224a01b91e837d35a56dccdced01
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++xdg shell protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
++Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8c9804f90cfc98a2336e185eb60a525124cb5359
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1313 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell">
++
++  <copyright>
++    Copyright © 2008-2013 Kristian Høgsberg
++    Copyright © 2013      Rafael Antognolli
++    Copyright © 2013      Jasper St. Pierre
++    Copyright © 2010-2013 Intel Corporation
++    Copyright © 2015-2017 Samsung Electronics Co., Ltd
++    Copyright © 2015-2017 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="xdg_wm_base" version="5">
++    <description summary="create desktop-style surfaces">
++      The xdg_wm_base interface is exposed as a global object enabling clients
++      to turn their wl_surfaces into windows in a desktop environment. It
++      defines the basic functionality needed for clients and the compositor to
++      create windows that can be dragged, resized, maximized, etc, as well as
++      creating transient windows such as popup menus.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++      <entry name="defunct_surfaces" value="1"
++           summary="xdg_wm_base was destroyed before children"/>
++      <entry name="not_the_topmost_popup" value="2"
++           summary="the client tried to map or destroy a non-topmost popup"/>
++      <entry name="invalid_popup_parent" value="3"
++           summary="the client specified an invalid popup parent surface"/>
++      <entry name="invalid_surface_state" value="4"
++           summary="the client provided an invalid surface state"/>
++      <entry name="invalid_positioner" value="5"
++           summary="the client provided an invalid positioner"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy xdg_wm_base">
++      Destroy this xdg_wm_base object.
++
++      Destroying a bound xdg_wm_base object while there are surfaces
++      still alive created by this xdg_wm_base object instance is illegal
++      and will result in a protocol error.
++      </description>
++    </request>
++
++    <request name="create_positioner">
++      <description summary="create a positioner object">
++      Create a positioner object. A positioner object is used to position
++      surfaces relative to some parent surface. See the interface description
++      and xdg_surface.get_popup for details.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_positioner"/>
++    </request>
++
++    <request name="get_xdg_surface">
++      <description summary="create a shell surface from a surface">
++      This creates an xdg_surface for the given surface. While xdg_surface
++      itself is not a role, the corresponding surface may only be assigned
++      a role extending xdg_surface, such as xdg_toplevel or xdg_popup. It is
++      illegal to create an xdg_surface for a wl_surface which already has an
++      assigned role and this will result in a protocol error.
++
++      This creates an xdg_surface for the given surface. An xdg_surface is
++      used as basis to define a role to a given surface, such as xdg_toplevel
++      or xdg_popup. It also manages functionality shared between xdg_surface
++      based surface roles.
++
++      See the documentation of xdg_surface for more details about what an
++      xdg_surface is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_surface"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++
++    <request name="pong">
++      <description summary="respond to a ping event">
++      A client must respond to a ping event with a pong request or
++      the client may be deemed unresponsive. See xdg_wm_base.ping.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the ping event"/>
++    </request>
++
++    <event name="ping">
++      <description summary="check if the client is alive">
++      The ping event asks the client if it's still alive. Pass the
++      serial specified in the event back to the compositor by sending
++      a "pong" request back with the specified serial. See xdg_wm_base.pong.
++
++      Compositors can use this to determine if the client is still
++      alive. It's unspecified what will happen if the client doesn't
++      respond to the ping request, or in what timeframe. Clients should
++      try to respond in a reasonable amount of time.
++
++      A compositor is free to ping in any way it wants, but a client must
++      always respond to any xdg_wm_base object it created.
++      </description>
++      <arg name="serial" type="uint" summary="pass this to the pong request"/>
++    </event>
++  </interface>
++
++  <interface name="xdg_positioner" version="5">
++    <description summary="child surface positioner">
++      The xdg_positioner provides a collection of rules for the placement of a
++      child surface relative to a parent surface. Rules can be defined to ensure
++      the child surface remains within the visible area's borders, and to
++      specify how the child surface changes its position, such as sliding along
++      an axis, or flipping around a rectangle. These positioner-created rules are
++      constrained by the requirement that a child surface must intersect with or
++      be at least partially adjacent to its parent surface.
++
++      See the various requests for details about possible rules.
++
++      At the time of the request, the compositor makes a copy of the rules
++      specified by the xdg_positioner. Thus, after the request is complete the
++      xdg_positioner object can be destroyed or reused; further changes to the
++      object will have no effect on previous usages.
++
++      For an xdg_positioner object to be considered complete, it must have a
++      non-zero size set by set_size, and a non-zero anchor rectangle set by
++      set_anchor_rect. Passing an incomplete xdg_positioner object when
++      positioning a surface raises an error.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_input" value="0" summary="invalid input provided"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_positioner object">
++      Notify the compositor that the xdg_positioner will no longer be used.
++      </description>
++    </request>
++
++    <request name="set_size">
++      <description summary="set the size of the to-be positioned rectangle">
++      Set the size of the surface that is to be positioned with the positioner
++      object. The size is in surface-local coordinates and corresponds to the
++      window geometry. See xdg_surface.set_window_geometry.
++
++      If a zero or negative size is set the invalid_input error is raised.
++      </description>
++      <arg name="width" type="int" summary="width of positioned rectangle"/>
++      <arg name="height" type="int" summary="height of positioned rectangle"/>
++    </request>
++
++    <request name="set_anchor_rect">
++      <description summary="set the anchor rectangle within the parent surface">
++      Specify the anchor rectangle within the parent surface that the child
++      surface will be placed relative to. The rectangle is relative to the
++      window geometry as defined by xdg_surface.set_window_geometry of the
++      parent surface.
++
++      When the xdg_positioner object is used to position a child surface, the
++      anchor rectangle may not extend outside the window geometry of the
++      positioned child's parent surface.
++
++      If a negative size is set the invalid_input error is raised.
++      </description>
++      <arg name="x" type="int" summary="x position of anchor rectangle"/>
++      <arg name="y" type="int" summary="y position of anchor rectangle"/>
++      <arg name="width" type="int" summary="width of anchor rectangle"/>
++      <arg name="height" type="int" summary="height of anchor rectangle"/>
++    </request>
++
++    <enum name="anchor">
++      <entry name="none" value="0"/>
++      <entry name="top" value="1"/>
++      <entry name="bottom" value="2"/>
++      <entry name="left" value="3"/>
++      <entry name="right" value="4"/>
++      <entry name="top_left" value="5"/>
++      <entry name="bottom_left" value="6"/>
++      <entry name="top_right" value="7"/>
++      <entry name="bottom_right" value="8"/>
++    </enum>
++
++    <request name="set_anchor">
++      <description summary="set anchor rectangle anchor">
++      Defines the anchor point for the anchor rectangle. The specified anchor
++      is used derive an anchor point that the child surface will be
++      positioned relative to. If a corner anchor is set (e.g. 'top_left' or
++      'bottom_right'), the anchor point will be at the specified corner;
++      otherwise, the derived anchor point will be centered on the specified
++      edge, or in the center of the anchor rectangle if no edge is specified.
++      </description>
++      <arg name="anchor" type="uint" enum="anchor"
++         summary="anchor"/>
++    </request>
++
++    <enum name="gravity">
++      <entry name="none" value="0"/>
++      <entry name="top" value="1"/>
++      <entry name="bottom" value="2"/>
++      <entry name="left" value="3"/>
++      <entry name="right" value="4"/>
++      <entry name="top_left" value="5"/>
++      <entry name="bottom_left" value="6"/>
++      <entry name="top_right" value="7"/>
++      <entry name="bottom_right" value="8"/>
++    </enum>
++
++    <request name="set_gravity">
++      <description summary="set child surface gravity">
++      Defines in what direction a surface should be positioned, relative to
++      the anchor point of the parent surface. If a corner gravity is
++      specified (e.g. 'bottom_right' or 'top_left'), then the child surface
++      will be placed towards the specified gravity; otherwise, the child
++      surface will be centered over the anchor point on any axis that had no
++      gravity specified.
++      </description>
++      <arg name="gravity" type="uint" enum="gravity"
++         summary="gravity direction"/>
++    </request>
++
++    <enum name="constraint_adjustment" bitfield="true">
++      <description summary="constraint adjustments">
++      The constraint adjustment value define ways the compositor will adjust
++      the position of the surface, if the unadjusted position would result
++      in the surface being partly constrained.
++
++      Whether a surface is considered 'constrained' is left to the compositor
++      to determine. For example, the surface may be partly outside the
++      compositor's defined 'work area', thus necessitating the child surface's
++      position be adjusted until it is entirely inside the work area.
++
++      The adjustments can be combined, according to a defined precedence: 1)
++      Flip, 2) Slide, 3) Resize.
++      </description>
++      <entry name="none" value="0">
++      <description summary="don't move the child surface when constrained">
++        Don't alter the surface position even if it is constrained on some
++        axis, for example partially outside the edge of an output.
++      </description>
++      </entry>
++      <entry name="slide_x" value="1">
++      <description summary="move along the x axis until unconstrained">
++        Slide the surface along the x axis until it is no longer constrained.
++
++        First try to slide towards the direction of the gravity on the x axis
++        until either the edge in the opposite direction of the gravity is
++        unconstrained or the edge in the direction of the gravity is
++        constrained.
++
++        Then try to slide towards the opposite direction of the gravity on the
++        x axis until either the edge in the direction of the gravity is
++        unconstrained or the edge in the opposite direction of the gravity is
++        constrained.
++      </description>
++      </entry>
++      <entry name="slide_y" value="2">
++      <description summary="move along the y axis until unconstrained">
++        Slide the surface along the y axis until it is no longer constrained.
++
++        First try to slide towards the direction of the gravity on the y axis
++        until either the edge in the opposite direction of the gravity is
++        unconstrained or the edge in the direction of the gravity is
++        constrained.
++
++        Then try to slide towards the opposite direction of the gravity on the
++        y axis until either the edge in the direction of the gravity is
++        unconstrained or the edge in the opposite direction of the gravity is
++        constrained.
++      </description>
++      </entry>
++      <entry name="flip_x" value="4">
++      <description summary="invert the anchor and gravity on the x axis">
++        Invert the anchor and gravity on the x axis if the surface is
++        constrained on the x axis. For example, if the left edge of the
++        surface is constrained, the gravity is 'left' and the anchor is
++        'left', change the gravity to 'right' and the anchor to 'right'.
++
++        If the adjusted position also ends up being constrained, the resulting
++        position of the flip_x adjustment will be the one before the
++        adjustment.
++      </description>
++      </entry>
++      <entry name="flip_y" value="8">
++      <description summary="invert the anchor and gravity on the y axis">
++        Invert the anchor and gravity on the y axis if the surface is
++        constrained on the y axis. For example, if the bottom edge of the
++        surface is constrained, the gravity is 'bottom' and the anchor is
++        'bottom', change the gravity to 'top' and the anchor to 'top'.
++
++        The adjusted position is calculated given the original anchor
++        rectangle and offset, but with the new flipped anchor and gravity
++        values.
++
++        If the adjusted position also ends up being constrained, the resulting
++        position of the flip_y adjustment will be the one before the
++        adjustment.
++      </description>
++      </entry>
++      <entry name="resize_x" value="16">
++      <description summary="horizontally resize the surface">
++        Resize the surface horizontally so that it is completely
++        unconstrained.
++      </description>
++      </entry>
++      <entry name="resize_y" value="32">
++      <description summary="vertically resize the surface">
++        Resize the surface vertically so that it is completely unconstrained.
++      </description>
++      </entry>
++    </enum>
++
++    <request name="set_constraint_adjustment">
++      <description summary="set the adjustment to be done when constrained">
++      Specify how the window should be positioned if the originally intended
++      position caused the surface to be constrained, meaning at least
++      partially outside positioning boundaries set by the compositor. The
++      adjustment is set by constructing a bitmask describing the adjustment to
++      be made when the surface is constrained on that axis.
++
++      If no bit for one axis is set, the compositor will assume that the child
++      surface should not change its position on that axis when constrained.
++
++      If more than one bit for one axis is set, the order of how adjustments
++      are applied is specified in the corresponding adjustment descriptions.
++
++      The default adjustment is none.
++      </description>
++      <arg name="constraint_adjustment" type="uint"
++         summary="bit mask of constraint adjustments"/>
++    </request>
++
++    <request name="set_offset">
++      <description summary="set surface position offset">
++      Specify the surface position offset relative to the position of the
++      anchor on the anchor rectangle and the anchor on the surface. For
++      example if the anchor of the anchor rectangle is at (x, y), the surface
++      has the gravity bottom|right, and the offset is (ox, oy), the calculated
++      surface position will be (x + ox, y + oy). The offset position of the
++      surface is the one used for constraint testing. See
++      set_constraint_adjustment.
++
++      An example use case is placing a popup menu on top of a user interface
++      element, while aligning the user interface element of the parent surface
++      with some user interface element placed somewhere in the popup surface.
++      </description>
++      <arg name="x" type="int" summary="surface position x offset"/>
++      <arg name="y" type="int" summary="surface position y offset"/>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <request name="set_reactive" since="3">
++      <description summary="continuously reconstrain the surface">
++      When set reactive, the surface is reconstrained if the conditions used
++      for constraining changed, e.g. the parent window moved.
++
++      If the conditions changed and the popup was reconstrained, an
++      xdg_popup.configure event is sent with updated geometry, followed by an
++      xdg_surface.configure event.
++      </description>
++    </request>
++
++    <request name="set_parent_size" since="3">
++      <description summary="">
++      Set the parent window geometry the compositor should use when
++      positioning the popup. The compositor may use this information to
++      determine the future state the popup should be constrained using. If
++      this doesn't match the dimension of the parent the popup is eventually
++      positioned against, the behavior is undefined.
++
++      The arguments are given in the surface-local coordinate space.
++      </description>
++      <arg name="parent_width" type="int"
++         summary="future window geometry width of parent"/>
++      <arg name="parent_height" type="int"
++         summary="future window geometry height of parent"/>
++    </request>
++
++    <request name="set_parent_configure" since="3">
++      <description summary="set parent configure this is a response to">
++      Set the serial of an xdg_surface.configure event this positioner will be
++      used in response to. The compositor may use this information together
++      with set_parent_size to determine what future state the popup should be
++      constrained using.
++      </description>
++      <arg name="serial" type="uint"
++         summary="serial of parent configure event"/>
++    </request>
++  </interface>
++
++  <interface name="xdg_surface" version="5">
++    <description summary="desktop user interface surface base interface">
++      An interface that may be implemented by a wl_surface, for
++      implementations that provide a desktop-style user interface.
++
++      It provides a base set of functionality required to construct user
++      interface elements requiring management by the compositor, such as
++      toplevel windows, menus, etc. The types of functionality are split into
++      xdg_surface roles.
++
++      Creating an xdg_surface does not set the role for a wl_surface. In order
++      to map an xdg_surface, the client must create a role-specific object
++      using, e.g., get_toplevel, get_popup. The wl_surface for any given
++      xdg_surface can have at most one role, and may not be assigned any role
++      not based on xdg_surface.
++
++      A role must be assigned before any other requests are made to the
++      xdg_surface object.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_surface state to take effect.
++
++      Creating an xdg_surface from a wl_surface which has a buffer attached or
++      committed is a client error, and any attempts by a client to attach or
++      manipulate a buffer prior to the first xdg_surface.configure call must
++      also be treated as errors.
++
++      After creating a role-specific object and setting it up, the client must
++      perform an initial commit without any buffer attached. The compositor
++      will reply with an xdg_surface.configure event. The client must
++      acknowledge it and is then allowed to attach a buffer to map the surface.
++
++      Mapping an xdg_surface-based role surface is defined as making it
++      possible for the surface to be shown by the compositor. Note that
++      a mapped surface is not guaranteed to be visible once it is mapped.
++
++      For an xdg_surface to be mapped by the compositor, the following
++      conditions must be met:
++      (1) the client has assigned an xdg_surface-based role to the surface
++      (2) the client has set and committed the xdg_surface state and the
++        role-dependent state to the surface
++      (3) the client has committed a buffer to the surface
++
++      A newly-unmapped surface is considered to have met condition (1) out
++      of the 3 required conditions for mapping a surface if its role surface
++      has not been destroyed, i.e. the client must perform the initial commit
++      again before attaching a buffer.
++    </description>
++
++    <enum name="error">
++      <entry name="not_constructed" value="1"/>
++      <entry name="already_constructed" value="2"/>
++      <entry name="unconfigured_buffer" value="3"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_surface">
++      Destroy the xdg_surface object. An xdg_surface must only be destroyed
++      after its role object has been destroyed.
++      </description>
++    </request>
++
++    <request name="get_toplevel">
++      <description summary="assign the xdg_toplevel surface role">
++      This creates an xdg_toplevel object for the given xdg_surface and gives
++      the associated wl_surface the xdg_toplevel role.
++
++      See the documentation of xdg_toplevel for more details about what an
++      xdg_toplevel is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_toplevel"/>
++    </request>
++
++    <request name="get_popup">
++      <description summary="assign the xdg_popup surface role">
++      This creates an xdg_popup object for the given xdg_surface and gives
++      the associated wl_surface the xdg_popup role.
++
++      If null is passed as a parent, a parent surface must be specified using
++      some other protocol, before committing the initial state.
++
++      See the documentation of xdg_popup for more details about what an
++      xdg_popup is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_popup"/>
++      <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
++      <arg name="positioner" type="object" interface="xdg_positioner"/>
++    </request>
++
++    <request name="set_window_geometry">
++      <description summary="set the new window geometry">
++      The window geometry of a surface is its "visible bounds" from the
++      user's perspective. Client-side decorations often have invisible
++      portions like drop-shadows which should be ignored for the
++      purposes of aligning, placing and constraining windows.
++
++      The window geometry is double buffered, and will be applied at the
++      time wl_surface.commit of the corresponding wl_surface is called.
++
++      When maintaining a position, the compositor should treat the (x, y)
++      coordinate of the window geometry as the top left corner of the window.
++      A client changing the (x, y) window geometry coordinate should in
++      general not alter the position of the window.
++
++      Once the window geometry of the surface is set, it is not possible to
++      unset it, and it will remain the same until set_window_geometry is
++      called again, even if a new subsurface or buffer is attached.
++
++      If never set, the value is the full bounds of the surface,
++      including any subsurfaces. This updates dynamically on every
++      commit. This unset is meant for extremely simple clients.
++
++      The arguments are given in the surface-local coordinate space of
++      the wl_surface associated with this xdg_surface.
++
++      The width and height must be greater than zero. Setting an invalid size
++      will raise an error. When applied, the effective window geometry will be
++      the set window geometry clamped to the bounding rectangle of the
++      combined geometry of the surface of the xdg_surface and the associated
++      subsurfaces.
++      </description>
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="ack_configure">
++      <description summary="ack a configure event">
++      When a configure event is received, if a client commits the
++      surface in response to the configure event, then the client
++      must make an ack_configure request sometime before the commit
++      request, passing along the serial of the configure event.
++
++      For instance, for toplevel surfaces the compositor might use this
++      information to move a surface to the top left only when the client has
++      drawn itself for the maximized or fullscreen state.
++
++      If the client receives multiple configure events before it
++      can respond to one, it only has to ack the last configure event.
++
++      A client is not required to commit immediately after sending
++      an ack_configure request - it may even ack_configure several times
++      before its next surface commit.
++
++      A client may send multiple ack_configure requests before committing, but
++      only the last request sent before a commit indicates which configure
++      event the client really is responding to.
++      </description>
++      <arg name="serial" type="uint" summary="the serial from the configure event"/>
++    </request>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++      The configure event marks the end of a configure sequence. A configure
++      sequence is a set of one or more events configuring the state of the
++      xdg_surface, including the final xdg_surface.configure event.
++
++      Where applicable, xdg_surface surface roles will during a configure
++      sequence extend this event as a latched state sent as events before the
++      xdg_surface.configure event. Such events should be considered to make up
++      a set of atomically applied configuration states, where the
++      xdg_surface.configure commits the accumulated state.
++
++      Clients should arrange their surface for the new states, and then send
++      an ack_configure request with the serial sent in this configure event at
++      some point before committing the new surface.
++
++      If the client receives multiple configure events before it can respond
++      to one, it is free to discard all but the last event it received.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the configure event"/>
++    </event>
++
++  </interface>
++
++  <interface name="xdg_toplevel" version="5">
++    <description summary="toplevel surface">
++      This interface defines an xdg_surface role which allows a surface to,
++      among other things, set window-like properties such as maximize,
++      fullscreen, and minimize, set application-specific metadata like title and
++      id, and well as trigger user interactive operations such as interactive
++      resize and move.
++
++      Unmapping an xdg_toplevel means that the surface cannot be shown
++      by the compositor until it is explicitly mapped again.
++      All active operations (e.g., move, resize) are canceled and all
++      attributes (e.g. title, state, stacking, ...) are discarded for
++      an xdg_toplevel surface when it is unmapped. The xdg_toplevel returns to
++      the state it had right after xdg_surface.get_toplevel. The client
++      can re-map the toplevel by perfoming a commit without any buffer
++      attached, waiting for a configure event and handling it as usual (see
++      xdg_surface description).
++
++      Attaching a null buffer to a toplevel unmaps the surface.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_toplevel">
++      This request destroys the role surface and unmaps the surface;
++      see "Unmapping" behavior in interface section for details.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="invalid_resize_edge" value="0" summary="provided value is
++        not a valid variant of the resize_edge enum"/>
++    </enum>
++
++    <request name="set_parent">
++      <description summary="set the parent of this surface">
++      Set the "parent" of this surface. This surface should be stacked
++      above the parent surface and all other ancestor surfaces.
++
++      Parent surfaces should be set on dialogs, toolboxes, or other
++      "auxiliary" surfaces, so that the parent is raised when the dialog
++      is raised.
++
++      Setting a null parent for a child surface unsets its parent. Setting
++      a null parent for a surface which currently has no parent is a no-op.
++
++      Only mapped surfaces can have child surfaces. Setting a parent which
++      is not mapped is equivalent to setting a null parent. If a surface
++      becomes unmapped, its children's parent is set to the parent of
++      the now-unmapped surface. If the now-unmapped surface has no parent,
++      its children's parent is unset. If the now-unmapped surface becomes
++      mapped again, its parent-child relationship is not restored.
++      </description>
++      <arg name="parent" type="object" interface="xdg_toplevel" allow-null="true"/>
++    </request>
++
++    <request name="set_title">
++      <description summary="set surface title">
++      Set a short title for the surface.
++
++      This string may be used to identify the surface in a task bar,
++      window list, or other user interface elements provided by the
++      compositor.
++
++      The string must be encoded in UTF-8.
++      </description>
++      <arg name="title" type="string"/>
++    </request>
++
++    <request name="set_app_id">
++      <description summary="set application ID">
++      Set an application identifier for the surface.
++
++      The app ID identifies the general class of applications to which
++      the surface belongs. The compositor can use this to group multiple
++      surfaces together, or to determine how to launch a new application.
++
++      For D-Bus activatable applications, the app ID is used as the D-Bus
++      service name.
++
++      The compositor shell will try to group application surfaces together
++      by their app ID. As a best practice, it is suggested to select app
++      ID's that match the basename of the application's .desktop file.
++      For example, "org.freedesktop.FooViewer" where the .desktop file is
++      "org.freedesktop.FooViewer.desktop".
++
++      Like other properties, a set_app_id request can be sent after the
++      xdg_toplevel has been mapped to update the property.
++
++      See the desktop-entry specification [0] for more details on
++      application identifiers and how they relate to well-known D-Bus
++      names and .desktop files.
++
++      [0] http://standards.freedesktop.org/desktop-entry-spec/
++      </description>
++      <arg name="app_id" type="string"/>
++    </request>
++
++    <request name="show_window_menu">
++      <description summary="show the window menu">
++      Clients implementing client-side decorations might want to show
++      a context menu when right-clicking on the decorations, giving the
++      user a menu that they can use to maximize or minimize the window.
++
++      This request asks the compositor to pop up such a window menu at
++      the given position, relative to the local surface coordinates of
++      the parent surface. There are no guarantees as to what menu items
++      the window menu contains.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++      <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++    </request>
++
++    <request name="move">
++      <description summary="start an interactive move">
++      Start an interactive, user-driven move of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive move (touch,
++      pointer, etc).
++
++      The server may ignore move requests depending on the state of
++      the surface (e.g. fullscreen or maximized), or if the passed serial
++      is no longer valid.
++
++      If triggered, the surface will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the move. It is up to the
++      compositor to visually indicate that the move is taking place, such as
++      updating a pointer cursor, during the move. There is no guarantee
++      that the device focus will return when the move is completed.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++    </request>
++
++    <enum name="resize_edge">
++      <description summary="edge values for resizing">
++      These values are used to indicate which edge of a surface
++      is being dragged in a resize operation.
++      </description>
++      <entry name="none" value="0"/>
++      <entry name="top" value="1"/>
++      <entry name="bottom" value="2"/>
++      <entry name="left" value="4"/>
++      <entry name="top_left" value="5"/>
++      <entry name="bottom_left" value="6"/>
++      <entry name="right" value="8"/>
++      <entry name="top_right" value="9"/>
++      <entry name="bottom_right" value="10"/>
++    </enum>
++
++    <request name="resize">
++      <description summary="start an interactive resize">
++      Start a user-driven, interactive resize of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive resize (touch,
++      pointer, etc).
++
++      The server may ignore resize requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++
++      If triggered, the client will receive configure events with the
++      "resize" state enum value and the expected sizes. See the "resize"
++      enum value for more details about what is required. The client
++      must also acknowledge configure events using "ack_configure". After
++      the resize is completed, the client will receive another "configure"
++      event without the resize state.
++
++      If triggered, the surface also will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++      compositor to visually indicate that the resize is taking place,
++      such as updating a pointer cursor, during the resize. There is no
++      guarantee that the device focus will return when the resize is
++      completed.
++
++      The edges parameter specifies how the surface should be resized, and
++      is one of the values of the resize_edge enum. Values not matching
++      a variant of the enum will cause a protocol error. The compositor
++      may use this information to update the surface position for example
++      when dragging the top left corner. The compositor may also use
++      this information to adapt its behavior, e.g. choose an appropriate
++      cursor image.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="edges" type="uint" enum="resize_edge" summary="which edge or corner is being dragged"/>
++    </request>
++
++    <enum name="state">
++      <description summary="types of state on the surface">
++      The different state values used on the surface. This is designed for
++      state values like maximized, fullscreen. It is paired with the
++      configure event to ensure that both the client and the compositor
++      setting the state can be synchronized.
++
++      States set in this way are double-buffered. They will get applied on
++      the next commit.
++      </description>
++      <entry name="maximized" value="1" summary="the surface is maximized">
++      <description summary="the surface is maximized">
++        The surface is maximized. The window geometry specified in the configure
++        event must be obeyed by the client.
++
++        The client should draw without shadow or other
++        decoration outside of the window geometry.
++      </description>
++      </entry>
++      <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++      <description summary="the surface is fullscreen">
++        The surface is fullscreen. The window geometry specified in the
++        configure event is a maximum; the client cannot resize beyond it. For
++        a surface to cover the whole fullscreened area, the geometry
++        dimensions must be obeyed by the client. For more details, see
++        xdg_toplevel.set_fullscreen.
++      </description>
++      </entry>
++      <entry name="resizing" value="3" summary="the surface is being resized">
++      <description summary="the surface is being resized">
++        The surface is being resized. The window geometry specified in the
++        configure event is a maximum; the client cannot resize beyond it.
++        Clients that have aspect ratio or cell sizing configuration can use
++        a smaller size, however.
++      </description>
++      </entry>
++      <entry name="activated" value="4" summary="the surface is now activated">
++      <description summary="the surface is now activated">
++        Client window decorations should be painted as if the window is
++        active. Do not assume this means that the window actually has
++        keyboard or pointer focus.
++      </description>
++      </entry>
++      <entry name="tiled_left" value="5" since="2">
++      <description summary="the surface’s left edge is tiled">
++        The window is currently in a tiled layout and the left edge is
++        considered to be adjacent to another part of the tiling grid.
++      </description>
++      </entry>
++      <entry name="tiled_right" value="6" since="2">
++      <description summary="the surface’s right edge is tiled">
++        The window is currently in a tiled layout and the right edge is
++        considered to be adjacent to another part of the tiling grid.
++      </description>
++      </entry>
++      <entry name="tiled_top" value="7" since="2">
++      <description summary="the surface’s top edge is tiled">
++        The window is currently in a tiled layout and the top edge is
++        considered to be adjacent to another part of the tiling grid.
++      </description>
++      </entry>
++      <entry name="tiled_bottom" value="8" since="2">
++      <description summary="the surface’s bottom edge is tiled">
++        The window is currently in a tiled layout and the bottom edge is
++        considered to be adjacent to another part of the tiling grid.
++      </description>
++      </entry>
++    </enum>
++
++    <request name="set_max_size">
++      <description summary="set the maximum size">
++      Set a maximum size for the window.
++
++      The client can specify a maximum size so that the compositor does
++      not try to configure the window beyond this size.
++
++      The width and height arguments are in window geometry coordinates.
++      See xdg_surface.set_window_geometry.
++
++      Values set in this way are double-buffered. They will get applied
++      on the next commit.
++
++      The compositor can use this information to allow or disallow
++      different states like maximize or fullscreen and draw accurate
++      animations.
++
++      Similarly, a tiling window manager may use this information to
++      place and resize client windows in a more effective way.
++
++      The client should not rely on the compositor to obey the maximum
++      size. The compositor may decide to ignore the values set by the
++      client and request a larger size.
++
++      If never set, or a value of zero in the request, means that the
++      client has no expected maximum size in the given dimension.
++      As a result, a client wishing to reset the maximum size
++      to an unspecified state can use zero for width and height in the
++      request.
++
++      Requesting a maximum size to be smaller than the minimum size of
++      a surface is illegal and will result in a protocol error.
++
++      The width and height must be greater than or equal to zero. Using
++      strictly negative values for width and height will result in a
++      protocol error.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_min_size">
++      <description summary="set the minimum size">
++      Set a minimum size for the window.
++
++      The client can specify a minimum size so that the compositor does
++      not try to configure the window below this size.
++
++      The width and height arguments are in window geometry coordinates.
++      See xdg_surface.set_window_geometry.
++
++      Values set in this way are double-buffered. They will get applied
++      on the next commit.
++
++      The compositor can use this information to allow or disallow
++      different states like maximize or fullscreen and draw accurate
++      animations.
++
++      Similarly, a tiling window manager may use this information to
++      place and resize client windows in a more effective way.
++
++      The client should not rely on the compositor to obey the minimum
++      size. The compositor may decide to ignore the values set by the
++      client and request a smaller size.
++
++      If never set, or a value of zero in the request, means that the
++      client has no expected minimum size in the given dimension.
++      As a result, a client wishing to reset the minimum size
++      to an unspecified state can use zero for width and height in the
++      request.
++
++      Requesting a minimum size to be larger than the maximum size of
++      a surface is illegal and will result in a protocol error.
++
++      The width and height must be greater than or equal to zero. Using
++      strictly negative values for width and height will result in a
++      protocol error.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_maximized">
++      <description summary="maximize the window">
++      Maximize the surface.
++
++      After requesting that the surface should be maximized, the compositor
++      will respond by emitting a configure event. Whether this configure
++      actually sets the window maximized is subject to compositor policies.
++      The client must then update its content, drawing in the configured
++      state. The client must also acknowledge the configure when committing
++      the new content (see ack_configure).
++
++      It is up to the compositor to decide how and where to maximize the
++      surface, for example which output and what region of the screen should
++      be used.
++
++      If the surface was already maximized, the compositor will still emit
++      a configure event with the "maximized" state.
++
++      If the surface is in a fullscreen state, this request has no direct
++      effect. It may alter the state the surface is returned to when
++      unmaximized unless overridden by the compositor.
++      </description>
++    </request>
++
++    <request name="unset_maximized">
++      <description summary="unmaximize the window">
++      Unmaximize the surface.
++
++      After requesting that the surface should be unmaximized, the compositor
++      will respond by emitting a configure event. Whether this actually
++      un-maximizes the window is subject to compositor policies.
++      If available and applicable, the compositor will include the window
++      geometry dimensions the window had prior to being maximized in the
++      configure event. The client must then update its content, drawing it in
++      the configured state. The client must also acknowledge the configure
++      when committing the new content (see ack_configure).
++
++      It is up to the compositor to position the surface after it was
++      unmaximized; usually the position the surface had before maximizing, if
++      applicable.
++
++      If the surface was already not maximized, the compositor will still
++      emit a configure event without the "maximized" state.
++
++      If the surface is in a fullscreen state, this request has no direct
++      effect. It may alter the state the surface is returned to when
++      unmaximized unless overridden by the compositor.
++      </description>
++    </request>
++
++    <request name="set_fullscreen">
++      <description summary="set the window as fullscreen on an output">
++      Make the surface fullscreen.
++
++      After requesting that the surface should be fullscreened, the
++      compositor will respond by emitting a configure event. Whether the
++      client is actually put into a fullscreen state is subject to compositor
++      policies. The client must also acknowledge the configure when
++      committing the new content (see ack_configure).
++
++      The output passed by the request indicates the client's preference as
++      to which display it should be set fullscreen on. If this value is NULL,
++      it's up to the compositor to choose which display will be used to map
++      this surface.
++
++      If the surface doesn't cover the whole output, the compositor will
++      position the surface in the center of the output and compensate with
++      with border fill covering the rest of the output. The content of the
++      border fill is undefined, but should be assumed to be in some way that
++      attempts to blend into the surrounding area (e.g. solid black).
++
++      If the fullscreened surface is not opaque, the compositor must make
++      sure that other screen content not part of the same surface tree (made
++      up of subsurfaces, popups or similarly coupled surfaces) are not
++      visible below the fullscreened surface.
++      </description>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++    </request>
++
++    <request name="unset_fullscreen">
++      <description summary="unset the window as fullscreen">
++      Make the surface no longer fullscreen.
++
++      After requesting that the surface should be unfullscreened, the
++      compositor will respond by emitting a configure event.
++      Whether this actually removes the fullscreen state of the client is
++      subject to compositor policies.
++
++      Making a surface unfullscreen sets states for the surface based on the following:
++      * the state(s) it may have had before becoming fullscreen
++      * any state(s) decided by the compositor
++      * any state(s) requested by the client while the surface was fullscreen
++
++      The compositor may include the previous window geometry dimensions in
++      the configure event, if applicable.
++
++      The client must also acknowledge the configure when committing the new
++      content (see ack_configure).
++      </description>
++    </request>
++
++    <request name="set_minimized">
++      <description summary="set the window as minimized">
++      Request that the compositor minimize your surface. There is no
++      way to know if the surface is currently minimized, nor is there
++      any way to unset minimization on this surface.
++
++      If you are looking to throttle redrawing when minimized, please
++      instead use the wl_surface.frame event for this, as this will
++      also work with live previews on windows in Alt-Tab, Expose or
++      similar compositor features.
++      </description>
++    </request>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++      This configure event asks the client to resize its toplevel surface or
++      to change its state. The configured state should not be applied
++      immediately. See xdg_surface.configure for details.
++
++      The width and height arguments specify a hint to the window
++      about how its surface should be resized in window geometry
++      coordinates. See set_window_geometry.
++
++      If the width or height arguments are zero, it means the client
++      should decide its own window dimension. This may happen when the
++      compositor needs to configure the state of the surface but doesn't
++      have any information about any previous or expected dimension.
++
++      The states listed in the event specify how the width/height
++      arguments should be interpreted, and possibly how it should be
++      drawn.
++
++      Clients must send an ack_configure in response to this event. See
++      xdg_surface.configure and xdg_surface.ack_configure for details.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++      <arg name="states" type="array"/>
++    </event>
++
++    <event name="close">
++      <description summary="surface wants to be closed">
++      The close event is sent by the compositor when the user
++      wants the surface to be closed. This should be equivalent to
++      the user clicking the close button in client-side decorations,
++      if your application has any.
++
++      This is only a request that the user intends to close the
++      window. The client may choose to ignore this request, or show
++      a dialog to ask the user to save their data, etc.
++      </description>
++    </event>
++
++    <!-- Version 4 additions -->
++
++    <event name="configure_bounds" since="4">
++      <description summary="recommended window geometry bounds">
++      The configure_bounds event may be sent prior to a xdg_toplevel.configure
++      event to communicate the bounds a window geometry size is recommended
++      to constrain to.
++
++      The passed width and height are in surface coordinate space. If width
++      and height are 0, it means bounds is unknown and equivalent to as if no
++      configure_bounds event was ever sent for this surface.
++
++      The bounds can for example correspond to the size of a monitor excluding
++      any panels or other shell components, so that a surface isn't created in
++      a way that it cannot fit.
++
++      The bounds may change at any point, and in such a case, a new
++      xdg_toplevel.configure_bounds will be sent, followed by
++      xdg_toplevel.configure and xdg_surface.configure.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </event>
++
++    <!-- Version 5 additions -->
++
++    <enum name="wm_capabilities" since="5">
++      <entry name="window_menu" value="1" summary="show_window_menu is available"/>
++      <entry name="maximize" value="2" summary="set_maximized and unset_maximized are available"/>
++      <entry name="fullscreen" value="3" summary="set_fullscreen and unset_fullscreen are available"/>
++      <entry name="minimize" value="4" summary="set_minimized is available"/>
++    </enum>
++
++    <event name="wm_capabilities" since="5">
++      <description summary="compositor capabilities">
++      This event advertises the capabilities supported by the compositor. If
++      a capability isn't supported, clients should hide or disable the UI
++      elements that expose this functionality. For instance, if the
++      compositor doesn't advertise support for minimized toplevels, a button
++      triggering the set_minimized request should not be displayed.
++
++      The compositor will ignore requests it doesn't support. For instance,
++      a compositor which doesn't advertise support for minimized will ignore
++      set_minimized requests.
++
++      Compositors must send this event once before the first
++      xdg_surface.configure event. When the capabilities change, compositors
++      must send this event again and then send an xdg_surface.configure
++      event.
++
++      The configured state should not be applied immediately. See
++      xdg_surface.configure for details.
++
++      The capabilities are sent as an array of 32-bit unsigned integers in
++      native endianness.
++      </description>
++      <arg name="capabilities" type="array" summary="array of 32-bit capabilities"/>
++    </event>
++  </interface>
++
++  <interface name="xdg_popup" version="5">
++    <description summary="short-lived, popup surfaces for menus">
++      A popup surface is a short-lived, temporary surface. It can be used to
++      implement for example menus, popovers, tooltips and other similar user
++      interface concepts.
++
++      A popup can be made to take an explicit grab. See xdg_popup.grab for
++      details.
++
++      When the popup is dismissed, a popup_done event will be sent out, and at
++      the same time the surface will be unmapped. See the xdg_popup.popup_done
++      event for details.
++
++      Explicitly destroying the xdg_popup object will also dismiss the popup and
++      unmap the surface. Clients that want to dismiss the popup when another
++      surface of their own is clicked should dismiss the popup using the destroy
++      request.
++
++      A newly created xdg_popup will be stacked on top of all previously created
++      xdg_popup surfaces associated with the same xdg_toplevel.
++
++      The parent of an xdg_popup must be mapped (see the xdg_surface
++      description) before the xdg_popup itself.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_popup state to take effect.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_grab" value="0"
++           summary="tried to grab after being mapped"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove xdg_popup interface">
++      This destroys the popup. Explicitly destroying the xdg_popup
++      object will also dismiss the popup, and unmap the surface.
++
++      If this xdg_popup is not the "topmost" popup, a protocol error
++      will be sent.
++      </description>
++    </request>
++
++    <request name="grab">
++      <description summary="make the popup take an explicit grab">
++      This request makes the created popup take an explicit grab. An explicit
++      grab will be dismissed when the user dismisses the popup, or when the
++      client destroys the xdg_popup. This can be done by the user clicking
++      outside the surface, using the keyboard, or even locking the screen
++      through closing the lid or a timeout.
++
++      If the compositor denies the grab, the popup will be immediately
++      dismissed.
++
++      This request must be used in response to some sort of user action like a
++      button press, key press, or touch down event. The serial number of the
++      event should be passed as 'serial'.
++
++      The parent of a grabbing popup must either be an xdg_toplevel surface or
++      another xdg_popup with an explicit grab. If the parent is another
++      xdg_popup it means that the popups are nested, with this popup now being
++      the topmost popup.
++
++      Nested popups must be destroyed in the reverse order they were created
++      in, e.g. the only popup you are allowed to destroy at all times is the
++      topmost one.
++
++      When compositors choose to dismiss a popup, they may dismiss every
++      nested grabbing popup as well. When a compositor dismisses popups, it
++      will follow the same dismissing order as required from the client.
++
++      If the topmost grabbing popup is destroyed, the grab will be returned to
++      the parent of the popup, if that parent previously had an explicit grab.
++
++      If the parent is a grabbing popup which has already been dismissed, this
++      popup will be immediately dismissed. If the parent is a popup that did
++      not take an explicit grab, an error will be raised.
++
++      During a popup grab, the client owning the grab will receive pointer
++      and touch events for all their surfaces as normal (similar to an
++      "owner-events" grab in X11 parlance), while the top most grabbing popup
++      will always have keyboard focus.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat"
++         summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++    </request>
++
++    <event name="configure">
++      <description summary="configure the popup surface">
++      This event asks the popup surface to configure itself given the
++      configuration. The configured state should not be applied immediately.
++      See xdg_surface.configure for details.
++
++      The x and y arguments represent the position the popup was placed at
++      given the xdg_positioner rule, relative to the upper left corner of the
++      window geometry of the parent surface.
++
++      For version 2 or older, the configure event for an xdg_popup is only
++      ever sent once for the initial configuration. Starting with version 3,
++      it may be sent again if the popup is setup with an xdg_positioner with
++      set_reactive requested, or in response to xdg_popup.reposition requests.
++      </description>
++      <arg name="x" type="int"
++         summary="x position relative to parent surface window geometry"/>
++      <arg name="y" type="int"
++         summary="y position relative to parent surface window geometry"/>
++      <arg name="width" type="int" summary="window geometry width"/>
++      <arg name="height" type="int" summary="window geometry height"/>
++    </event>
++
++    <event name="popup_done">
++      <description summary="popup interaction is done">
++      The popup_done event is sent out when a popup is dismissed by the
++      compositor. The client should destroy the xdg_popup object at this
++      point.
++      </description>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="reposition" since="3">
++      <description summary="recalculate the popup's location">
++      Reposition an already-mapped popup. The popup will be placed given the
++      details in the passed xdg_positioner object, and a
++      xdg_popup.repositioned followed by xdg_popup.configure and
++      xdg_surface.configure will be emitted in response. Any parameters set
++      by the previous positioner will be discarded.
++
++      The passed token will be sent in the corresponding
++      xdg_popup.repositioned event. The new popup position will not take
++      effect until the corresponding configure event is acknowledged by the
++      client. See xdg_popup.repositioned for details. The token itself is
++      opaque, and has no other special meaning.
++
++      If multiple reposition requests are sent, the compositor may skip all
++      but the last one.
++
++      If the popup is repositioned in response to a configure event for its
++      parent, the client should send an xdg_positioner.set_parent_configure
++      and possibly an xdg_positioner.set_parent_size request to allow the
++      compositor to properly constrain the popup.
++
++      If the popup is repositioned together with a parent that is being
++      resized, but not in response to a configure event, the client should
++      send an xdg_positioner.set_parent_size request.
++      </description>
++      <arg name="positioner" type="object" interface="xdg_positioner"/>
++      <arg name="token" type="uint" summary="reposition request token"/>
++    </request>
++
++    <event name="repositioned" since="3">
++      <description summary="signal the completion of a repositioned request">
++      The repositioned event is sent as part of a popup configuration
++      sequence, together with xdg_popup.configure and lastly
++      xdg_surface.configure to notify the completion of a reposition request.
++
++      The repositioned event is to notify about the completion of a
++      xdg_popup.reposition request. The token argument is the token passed
++      in the xdg_popup.reposition request.
++
++      Immediately after this event is emitted, xdg_popup.configure and
++      xdg_surface.configure will be sent with the updated size and position,
++      as well as a new configure serial.
++
++      The client should optionally update the content of the popup, but must
++      acknowledge the new popup configuration for the new position to take
++      effect. See xdg_surface.ack_configure for details.
++      </description>
++      <arg name="token" type="uint" summary="reposition request token"/>
++    </event>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..36bfbcc165e0be77a63be431337e322235b9095b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,6 @@@
++Linux DRM lease
++
++Maintainers:
++Drew DeVault <sir@cmpwn.com>
++Marius Vlad <marius.vlad@collabora.com>
++Xaver Hugl <xaver.hugl@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d4c960a18aff616cbef516fa8ea2699eb9c97990
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,303 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="drm_lease_v1">
++  <copyright>
++    Copyright © 2018 NXP
++    Copyright © 2019 Status Research &amp; Development GmbH.
++    Copyright © 2021 Xaver Hugl
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="wp_drm_lease_device_v1" version="1">
++    <description summary="lease device">
++      This protocol is used by Wayland compositors which act as Direct
++      Renderering Manager (DRM) masters to lease DRM resources to Wayland
++      clients.
++
++      The compositor will advertise one wp_drm_lease_device_v1 global for each
++      DRM node. Some time after a client binds to the wp_drm_lease_device_v1
++      global, the compositor will send a drm_fd event followed by zero, one or
++      more connector events. After all currently available connectors have been
++      sent, the compositor will send a wp_drm_lease_device_v1.done event.
++
++      When the list of connectors available for lease changes the compositor
++      will send wp_drm_lease_device_v1.connector events for added connectors and
++      wp_drm_lease_connector_v1.withdrawn events for removed connectors,
++      followed by a wp_drm_lease_device_v1.done event.
++
++      The compositor will indicate when a device is gone by removing the global
++      via a wl_registry.global_remove event. Upon receiving this event, the
++      client should destroy any matching wp_drm_lease_device_v1 object.
++
++      To destroy a wp_drm_lease_device_v1 object, the client must first issue
++      a release request. Upon receiving this request, the compositor will
++      immediately send a released event and destroy the object. The client must
++      continue to process and discard drm_fd and connector events until it
++      receives the released event. Upon receiving the released event, the
++      client can safely cleanup any client-side resources.
++
++      Warning! The protocol described in this file is currently in the testing
++      phase. Backward compatible changes may be added together with the
++      corresponding interface version bump. Backward incompatible changes can
++      only be done by creating a new major version of the extension.
++    </description>
++
++    <request name="create_lease_request">
++      <description summary="create a lease request object">
++        Creates a lease request object.
++
++        See the documentation for wp_drm_lease_request_v1 for details.
++      </description>
++      <arg name="id" type="new_id" interface="wp_drm_lease_request_v1" />
++    </request>
++
++    <request name="release">
++      <description summary="release this object">
++        Indicates the client no longer wishes to use this object. In response
++        the compositor will immediately send the released event and destroy
++        this object. It can however not guarantee that the client won't receive
++        connector events before the released event. The client must not send any
++        requests after this one, doing so will raise a wl_display error.
++        Existing connectors, lease request and leases will not be affected.
++      </description>
++    </request>
++
++    <event name="drm_fd">
++      <description summary="open a non-master fd for this DRM node">
++        The compositor will send this event when the wp_drm_lease_device_v1
++        global is bound, although there are no guarantees as to how long this
++        takes - the compositor might need to wait until regaining DRM master.
++        The included fd is a non-master DRM file descriptor opened for this
++        device and the compositor must not authenticate it.
++        The purpose of this event is to give the client the ability to
++        query DRM and discover information which may help them pick the
++        appropriate DRM device or select the appropriate connectors therein.
++      </description>
++      <arg name="fd" type="fd" summary="DRM file descriptor" />
++    </event>
++
++    <event name="connector">
++      <description summary="advertise connectors available for leases">
++        The compositor will use this event to advertise connectors available for
++        lease by clients. This object may be passed into a lease request to
++        indicate the client would like to lease that connector, see
++        wp_drm_lease_request_v1.request_connector for details. While the
++        compositor will make a best effort to not send disconnected connectors,
++        no guarantees can be made.
++
++        The compositor must send the drm_fd event before sending connectors.
++        After the drm_fd event it will send all available connectors but may
++        send additional connectors at any time.
++      </description>
++      <arg name="id" type="new_id" interface="wp_drm_lease_connector_v1" />
++    </event>
++
++    <event name="done">
++      <description summary="signals grouping of connectors">
++        The compositor will send this event to indicate that it has sent all
++        currently available connectors after the client binds to the global or
++        when it updates the connector list, for example on hotplug, drm master
++        change or when a leased connector becomes available again. It will
++        similarly send this event to group wp_drm_lease_connector_v1.withdrawn
++        events of connectors of this device.
++      </description>
++    </event>
++
++    <event name="released" type="destructor">
++      <description summary="the compositor has finished using the device">
++        This event is sent in response to the release request and indicates
++        that the compositor is done sending connector events.
++        The compositor will destroy this object immediately after sending the
++        event and it will become invalid. The client should release any
++        resources associated with this device after receiving this event.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="wp_drm_lease_connector_v1" version="1">
++    <description summary="a leasable DRM connector">
++      Represents a DRM connector which is available for lease. These objects are
++      created via wp_drm_lease_device_v1.connector events, and should be passed
++      to lease requests via wp_drm_lease_request_v1.request_connector.
++      Immediately after the wp_drm_lease_connector_v1 object is created the
++      compositor will send a name, a description, a connector_id and a done
++      event. When the description is updated the compositor will send a
++      description event followed by a done event.
++    </description>
++
++    <event name="name">
++      <description summary="name">
++        The compositor sends this event once the connector is created to
++        indicate the name of this connector. This will not change for the
++        duration of the Wayland session, but is not guaranteed to be consistent
++        between sessions.
++      </description>
++      <arg name="name" type="string" summary="connector name" />
++    </event>
++
++    <event name="description">
++      <description summary="description">
++        The compositor sends this event once the connector is created to provide
++        a human-readable description for this connector, which may be presented
++        to the user. The compositor may send this event multiple times over the
++        lifetime of this object to reflect changes in the description.
++      </description>
++      <arg name="description" type="string" summary="connector description" />
++    </event>
++
++    <event name="connector_id">
++      <description summary="connector_id">
++        The compositor sends this event once the connector is created to
++        indicate the DRM object ID which represents the underlying connector
++        that is being offered. Note that the final lease may include additional
++        object IDs, such as CRTCs and planes.
++      </description>
++      <arg name="connector_id" type="uint" summary="DRM connector ID" />
++    </event>
++
++    <event name="done">
++      <description summary="all properties have been sent">
++        This event is sent after all properties of a connector have been sent.
++        This allows changes to the properties to be seen as atomic even if they
++        happen via multiple events.
++      </description>
++    </event>
++
++    <event name="withdrawn">
++      <description summary="lease offer withdrawn">
++        Sent to indicate that the compositor will no longer honor requests for
++        DRM leases which include this connector. The client may still issue a
++        lease request including this connector, but the compositor will send
++        wp_drm_lease_v1.finished without issuing a lease fd. Compositors are
++        encouraged to send this event when they lose access to connector, for
++        example when the connector is hot-unplugged, when the connector gets
++        leased to a client or when the compositor loses DRM master.
++      </description>
++    </event>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy connector">
++        The client may send this request to indicate that it will not use this
++        connector. Clients are encouraged to send this after receiving the
++        "withdrawn" event so that the server can release the resources
++        associated with this connector offer. Neither existing lease requests
++        nor leases will be affected.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="wp_drm_lease_request_v1" version="1">
++    <description summary="DRM lease request">
++      A client that wishes to lease DRM resources will attach the list of
++      connectors advertised with wp_drm_lease_device_v1.connector that they
++      wish to lease, then use wp_drm_lease_request_v1.submit to submit the
++      request.
++    </description>
++
++    <enum name="error">
++      <entry name="wrong_device" value="0"
++             summary="requested a connector from a different lease device"/>
++      <entry name="duplicate_connector" value="1"
++             summary="requested a connector twice"/>
++      <entry name="empty_lease" value="2"
++             summary="requested a lease without requesting a connector"/>
++    </enum>
++
++    <request name="request_connector">
++      <description summary="request a connector for this lease">
++        Indicates that the client would like to lease the given connector.
++        This is only used as a suggestion, the compositor may choose to
++        include any resources in the lease it issues, or change the set of
++        leased resources at any time. Compositors are however encouraged to
++        include the requested connector and other resources necessary
++        to drive the connected output in the lease.
++
++        Requesting a connector that was created from a different lease device
++        than this lease request raises the wrong_device error. Requesting a
++        connector twice will raise the duplicate_connector error.
++      </description>
++      <arg name="connector" type="object"
++           interface="wp_drm_lease_connector_v1" />
++    </request>
++
++    <request name="submit" type="destructor">
++      <description summary="submit the lease request">
++        Submits the lease request and creates a new wp_drm_lease_v1 object.
++        After calling submit the compositor will immediately destroy this
++        object, issuing any more requests will cause a wl_diplay error.
++        The compositor doesn't make any guarantees about the events of the
++        lease object, clients cannot expect an immediate response.
++        Not requesting any connectors before submitting the lease request
++        will raise the empty_lease error.
++      </description>
++      <arg name="id" type="new_id" interface="wp_drm_lease_v1" />
++    </request>
++  </interface>
++
++  <interface name="wp_drm_lease_v1" version="1">
++    <description summary="a DRM lease">
++      A DRM lease object is used to transfer the DRM file descriptor to the
++      client and manage the lifetime of the lease.
++
++      Some time after the wp_drm_lease_v1 object is created, the compositor
++      will reply with the lease request's result. If the lease request is
++      granted, the compositor will send a lease_fd event. If the lease request
++      is denied, the compositor will send a finished event without a lease_fd
++      event.
++    </description>
++
++    <event name="lease_fd">
++      <description summary="shares the DRM file descriptor">
++        This event returns a file descriptor suitable for use with DRM-related
++        ioctls. The client should use drmModeGetLease to enumerate the DRM
++        objects which have been leased to them. The compositor guarantees it
++        will not use the leased DRM objects itself until it sends the finished
++        event. If the compositor cannot or will not grant a lease for the
++        requested connectors, it will not send this event, instead sending the
++        finished event.
++
++        The compositor will send this event at most once during this objects
++        lifetime.
++      </description>
++      <arg name="leased_fd" type="fd" summary="leased DRM file descriptor" />
++    </event>
++
++    <event name="finished">
++      <description summary="sent when the lease has been revoked">
++        The compositor uses this event to either reject a lease request, or if
++        it previously sent a lease_fd, to notify the client that the lease has
++        been revoked. If the client requires a new lease, they should destroy
++        this object and submit a new lease request. The compositor will send
++        no further events for this object after sending the finish event.
++        Compositors should revoke the lease when any of the leased resources
++        become unavailable, namely when a hot-unplug occurs or when the
++        compositor loses DRM master.
++      </description>
++    </event>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroys the lease object">
++        The client should send this to indicate that it no longer wishes to use
++        this lease. The compositor should use drmModeRevokeLease on the
++        appropriate file descriptor, if necessary.
++      </description>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..512c0dcd4d52c48fc5a14daa2714fdfcd7f19719
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++ext session lock protocol
++
++Maintainers:
++Isaac Freund <mail@isaacfreund.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5b292cdb873253fa573393e7abbb93e68c7f35cf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,282 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="ext_session_lock_v1">
++  <copyright>
++    Copyright 2021 Isaac Freund
++
++    Permission to use, copy, modify, and/or distribute this software for any
++    purpose with or without fee is hereby granted, provided that the above
++    copyright notice and this permission notice appear in all copies.
++
++    THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
++    WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
++    MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
++    ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
++    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
++    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
++  </copyright>
++
++  <description summary="secure session locking with arbitrary graphics">
++    This protocol allows for a privileged Wayland client to lock the session
++    and display arbitrary graphics while the session is locked.
++
++    The compositor may choose to restrict this protocol to a special client
++    launched by the compositor itself or expose it to all privileged clients,
++    this is compositor policy.
++
++    The client is responsible for performing authentication and informing the
++    compositor when the session should be unlocked. If the client dies while
++    the session is locked the session remains locked, possibly permanently
++    depending on compositor policy.
++
++    Warning! The protocol described in this file is currently in the
++    testing phase. Backward compatible changes may be added together with
++    the corresponding interface version bump. Backward incompatible changes
++    can only be done by creating a new major version of the extension.
++  </description>
++
++  <interface name="ext_session_lock_manager_v1" version="1">
++    <description summary="used to lock the session">
++      This interface is used to request that the session be locked.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the session lock manager object">
++        This informs the compositor that the session lock manager object will
++        no longer be used. Existing objects created through this interface
++        remain valid.
++      </description>
++    </request>
++
++    <request name="lock">
++      <description summary="attempt to lock the session">
++        This request creates a session lock and asks the compositor to lock the
++        session. The compositor will send either the ext_session_lock_v1.locked
++        or ext_session_lock_v1.finished event on the created object in
++        response to this request.
++      </description>
++      <arg name="id" type="new_id" interface="ext_session_lock_v1"/>
++    </request>
++  </interface>
++
++  <interface name="ext_session_lock_v1" version="1">
++    <description summary="manage lock state and create lock surfaces">
++      On creation of this object either the locked or finished event will
++      immediately be sent.
++
++      The locked event indicates that the session is locked. This means that
++      the compositor should stop rendering and providing input to normal
++      clients. Instead the compositor should blank all outputs with an opaque
++      color such that their normal content is fully hidden.
++
++      The only surfaces that should be rendered while the session is locked
++      are the lock surfaces created through this interface and optionally,
++      at the compositor's discretion, special privileged surfaces such as
++      input methods or portions of desktop shell UIs.
++
++      If the client dies while the session is locked, the compositor should not
++      unlock the session in response. It is acceptable for the session to be
++      permanently locked if this happens. The compositor may choose to continue
++      to display the lock surfaces the client had mapped before it died or
++      alternatively fall back to a solid color, this is compositor policy.
++
++      Compositors may also allow a secure way to recover the session, the
++      details of this are compositor policy. Compositors may allow a new
++      client to create a ext_session_lock_v1 object and take responsibility
++      for unlocking the session, they may even start a new lock client
++      instance automatically.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_destroy" value="0"
++        summary="attempted to destroy session lock while locked"/>
++      <entry name="invalid_unlock" value="1"
++        summary="unlock requested but locked event was never sent"/>
++      <entry name="role" value="2"
++        summary="given wl_surface already has a role"/>
++      <entry name="duplicate_output" value="3"
++        summary="given output already has a lock surface"/>
++      <entry name="already_constructed" value="4"
++        summary="given wl_surface has a buffer attached or committed"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the session lock">
++        This informs the compositor that the lock object will no longer be
++        used. Existing objects created through this interface remain valid.
++
++        After this request is made, lock surfaces created through this object
++        should be destroyed by the client as they will no longer be used by
++        the compositor.
++
++        It is a protocol error to make this request if the locked event was
++        sent, the unlock_and_destroy request must be used instead.
++      </description>
++    </request>
++
++    <event name="locked">
++      <description summary="session successfully locked">
++        This client is now responsible for displaying graphics while the
++        session is locked and deciding when to unlock the session.
++
++        Either this event or the finished event will be sent immediately on
++        creation of this object.
++
++        If this event is sent, making the destroy request is a protocol error,
++        the lock object may only be destroyed using the unlock_and_destroy
++        request.
++      </description>
++    </event>
++
++    <event name="finished">
++      <description summary="the session lock object should be destroyed">
++        The compositor has decided that the session lock should be
++        destroyed. Exactly when this event is sent is compositor policy, but
++        it will never be sent more than once for a given session lock object.
++
++        This might be sent because there is already another ext_session_lock_v1
++        object held by a client, or the compositor has decided to deny the
++        request to lock the session for some other reason. This might also
++        be sent because the compositor implements some alternative, secure
++        way to authenticate and unlock the session.
++
++        Either this event or the locked event will be sent exactly once on
++        creation of this object. If the locked event is sent on creation of
++        this object, the finished event may still be sent at some later time
++        in this object's lifetime, this is compositor policy.
++
++        Upon receiving this event, the client should make either the destroy
++        request or the unlock_and_destroy request, depending on whether or
++        not the locked event was received on this object.
++      </description>
++    </event>
++
++    <request name="get_lock_surface">
++      <description summary="create a lock surface for a given output">
++        The client is expected to create lock surfaces for all outputs
++        currently present and any new outputs as they are advertised. These
++        won't be displayed by the compositor unless the lock is successful
++        and the locked event is sent.
++
++        Providing a wl_surface which already has a role or already has a buffer
++        attached or committed is a protocol error, as is attaching/committing
++        a buffer before the first ext_session_lock_surface_v1.configure event.
++
++        Attempting to create more than one lock surface for a given output
++        is a duplicate_output protocol error.
++      </description>
++      <arg name="id" type="new_id" interface="ext_session_lock_surface_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="output" type="object" interface="wl_output"/>
++    </request>
++
++    <request name="unlock_and_destroy" type="destructor">
++      <description summary="unlock the session, destroying the object">
++        This request indicates that the session should be unlocked, for
++        example because the user has entered their password and it has been
++        verified by the client.
++
++        This request also informs the compositor that the lock object will
++        no longer be used and may be safely destroyed. Existing objects
++        created through this interface remain valid.
++
++        After this request is made, lock surfaces created through this object
++        should be destroyed by the client as they will no longer be used by
++        the compositor.
++
++        It is a protocol error to make this request if the locked event has
++        not been sent. In that case, the lock object may only be destroyed
++        using the destroy request.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="ext_session_lock_surface_v1" version="1">
++    <description summary="a surface displayed while the session is locked">
++      The client may use lock surfaces to display a screensaver, render a
++      dialog to enter a password and unlock the session, or however else it
++      sees fit.
++
++      On binding this interface the compositor will immediately send the
++      first configure event. After making the ack_configure request in
++      response to this event the client may attach and commit the first
++      buffer. Committing the surface before acking the first configure is a
++      protocol error. Committing the surface with a null buffer at any time
++      is a protocol error.
++
++      The compositor is free to handle keyboard/pointer focus for lock
++      surfaces however it chooses. A reasonable way to do this would be to
++      give the first lock surface created keyboard focus and change keyboard
++      focus if the user clicks on other surfaces.
++    </description>
++
++    <enum name="error">
++      <entry name="commit_before_first_ack" value="0"
++        summary="surface committed before first ack_configure request"/>
++      <entry name="null_buffer" value="1"
++        summary="surface committed with a null buffer"/>
++      <entry name="dimensions_mismatch" value="2"
++        summary="failed to match ack'd width/height"/>
++      <entry name="invalid_serial" value="3"
++        summary="serial provided in ack_configure is invalid"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the lock surface object">
++        This informs the compositor that the lock surface object will no
++        longer be used.
++
++        It is recommended for a lock client to destroy lock surfaces if
++        their corresponding wl_output global is removed.
++
++        If a lock surface on an active output is destroyed before the
++        ext_session_lock_v1.unlock_and_destroy event is sent, the compositor
++        must fall back to rendering a solid color.
++      </description>
++    </request>
++
++    <request name="ack_configure">
++      <description summary="ack a configure event">
++        When a configure event is received, if a client commits the surface
++        in response to the configure event, then the client must make an
++        ack_configure request sometime before the commit request, passing
++        along the serial of the configure event.
++
++        If the client receives multiple configure events before it can
++        respond to one, it only has to ack the last configure event.
++
++        A client is not required to commit immediately after sending an
++        ack_configure request - it may even ack_configure several times
++        before its next surface commit.
++
++        A client may send multiple ack_configure requests before committing,
++        but only the last request sent before a commit indicates which
++        configure event the client really is responding to.
++
++        Sending an ack_configure request consumes the configure event
++        referenced by the given serial, as well as all older configure events
++        sent on this object.
++
++        It is a protocol error to issue multiple ack_configure requests
++        referencing the same configure event or to issue an ack_configure
++        request referencing a configure event older than the last configure
++        event acked for a given lock surface.
++      </description>
++      <arg name="serial" type="uint" summary="serial from the configure event"/>
++    </request>
++
++    <event name="configure">
++      <description summary="the client should resize its surface">
++        This event is sent once on binding the interface and may be sent again
++        at the compositor's discretion, for example if output geometry changes.
++
++        The width and height are in surface-local coordinates and are exact
++        requirements. Failing to match these surface dimensions in the next
++        commit after acking a configure is a protocol error.
++      </description>
++      <arg name="serial" type="uint" summary="serial for use in ack_configure"/>
++      <arg name="width" type="uint"/>
++      <arg name="height" type="uint"/>
++    </event>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b3ae55e04421c7524a45d8f92cee9cc14b2846a4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Single-pixel buffer protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b157155781450cba2280e1fd7bc3137c5c2616f2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,69 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="single_pixel_buffer_v1">
++  <copyright>
++    Copyright © 2022 Simon Ser
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="single pixel buffer factory">
++    This protocol extension allows clients to create single-pixel buffers.
++
++    Compositors supporting this protocol extension should also support the
++    viewporter protocol extension. Clients may use viewporter to scale a
++    single-pixel buffer to a desired size.
++
++    Warning! The protocol described in this file is currently in the testing
++    phase. Backward compatible changes may be added together with the
++    corresponding interface version bump. Backward incompatible changes can
++    only be done by creating a new major version of the extension.
++  </description>
++
++  <interface name="wp_single_pixel_buffer_manager_v1" version="1">
++    <description summary="global factory for single-pixel buffers">
++      The wp_single_pixel_buffer_manager_v1 interface is a factory for
++      single-pixel buffers.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the manager">
++        Destroy the wp_single_pixel_buffer_manager_v1 object.
++
++        The child objects created via this interface are unaffected.
++      </description>
++    </request>
++
++    <request name="create_u32_rgba_buffer">
++      <description summary="create a 1×1 buffer from 32-bit RGBA values">
++        Create a single-pixel buffer from four 32-bit RGBA values.
++
++        Unless specified in another protocol extension, the RGBA values use
++        pre-multiplied alpha.
++
++        The width and height of the buffer are 1.
++      </description>
++      <arg name="id" type="new_id" interface="wl_buffer"/>
++      <arg name="r" type="uint" summary="value of the buffer's red channel"/>
++      <arg name="g" type="uint" summary="value of the buffer's green channel"/>
++      <arg name="b" type="uint" summary="value of the buffer's blue channel"/>
++      <arg name="a" type="uint" summary="value of the buffer's alpha channel"/>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cdd4d96cc412983d8e5bd1671efdb256b4315cf3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++XDG Activation protocol
++
++Maintainers:
++Aleix Pol Gonzalez <aleixpol@kde.org>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3bd03ee202d55fadbfce02e45a125918f2b5f092
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,63 @@@
++Interoperation with X11
++=======================
++
++*This document is non-normative.*
++
++The former
++`X11 Startup notification protocol <https://cgit.freedesktop.org/startup-notification/tree/doc/startup-notification.txt>`_
++defines the use of the ``DESKTOP_STARTUP_ID`` environment variable to propagate
++startup sequences ("activation tokens" in this protocol) between launcher and
++launchee.
++
++These startup sequence IDs are defined as a globally unique string with a
++``[unique]_TIME[timestamp]`` format, where the ID as a whole is used for startup
++notification and the timestamp is used for focus requests and focus stealing
++prevention.
++
++In order to observe mixed usage scenarios where Wayland and X11 clients might
++be launching each other, it is possible for a compositor to manage a shared
++pool of activation tokens.
++
++Scenario 1. Wayland client spawns X11 client
++--------------------------------------------
++
++1. Wayland client requests token.
++2. Wayland client spawns X11 client, sets ``$DESKTOP_STARTUP_ID`` in its
++   environment with the token string.
++3. X11 client starts.
++4. X11 client sends startup-notification ``remove`` message with the activation
++   ``$DESKTOP_STARTUP_ID`` content.
++5. Compositor receives startup notification message, matches ID with
++   the common pool.
++6. The startup feedback is finished.
++7. X11 client requests focus.
++8. Compositor applies internal policies to allow/deny focus switch.
++
++Scenario 2. X11 client spawns Wayland client
++--------------------------------------------
++
++1. X11 client builds a "globally unique" ID
++2. X11 client sends startup-notification ``new`` message with the ID.
++3. Compositor receives startup notification message, adds the ID to
++   the common pool.
++4. X11 client spawns Wayland client, sets ``$DESKTOP_STARTUP_ID`` in its
++   environment.
++5. Wayland client starts.
++6. Wayland client requests surface activation with the activation token,
++   as received from ``$DESKTOP_STARTUP_ID``.
++7. Compositor receives the request, matches ID with the common pool
++8. The startup feedback is finished.
++9. Compositor applies internal policies to allow/deny focus switch.
++
++Caveats
++-------
++
++- For legacy reasons, the usage of ``$DESKTOP_STARTUP_ID`` (even if as a
++  fallback) should be observed in compositors and clients that are
++  concerned with X11 interoperation.
++
++- Depending on the X11 startup-notification implementation in use by the
++  compositor, the usage of the ``_TIME[timestamp]`` suffix may be mandatory
++  for its correct behavior in the first scenario, the startup-notification
++  reference library is one such implementation. Compositors may work
++  this around by adding a matching suffix to the generated activation tokens.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4994298c1ed63d99d481b4357c670356ac25f445
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,200 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_activation_v1">
++
++  <copyright>
++    Copyright © 2020 Aleix Pol Gonzalez &lt;aleixpol@kde.org&gt;
++    Copyright © 2020 Carlos Garnacho &lt;carlosg@gnome.org&gt;
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for requesting activation of surfaces">
++    The way for a client to pass focus to another toplevel is as follows.
++
++    The client that intends to activate another toplevel uses the
++    xdg_activation_v1.get_activation_token request to get an activation token.
++    This token is then forwarded to the client, which is supposed to activate
++    one of its surfaces, through a separate band of communication.
++
++    One established way of doing this is through the XDG_ACTIVATION_TOKEN
++    environment variable of a newly launched child process. The child process
++    should unset the environment variable again right after reading it out in
++    order to avoid propagating it to other child processes.
++
++    Another established way exists for Applications implementing the D-Bus
++    interface org.freedesktop.Application, which should get their token under
++    XDG_ACTIVATION_TOKEN on their platform_data.
++
++    In general activation tokens may be transferred across clients through
++    means not described in this protocol.
++
++    The client to be activated will then pass the token
++    it received to the xdg_activation_v1.activate request. The compositor can
++    then use this token to decide how to react to the activation request.
++
++    The token the activating client gets may be ineffective either already at
++    the time it receives it, for example if it was not focused, for focus
++    stealing prevention. The activating client will have no way to discover
++    the validity of the token, and may still forward it to the to be activated
++    client.
++
++    The created activation token may optionally get information attached to it
++    that can be used by the compositor to identify the application that we
++    intend to activate. This can for example be used to display a visual hint
++    about what application is being started.
++
++    Warning! The protocol described in this file is currently in the testing
++    phase. Backward compatible changes may be added together with the
++    corresponding interface version bump. Backward incompatible changes can
++    only be done by creating a new major version of the extension.
++  </description>
++
++  <interface name="xdg_activation_v1" version="1">
++    <description summary="interface for activating surfaces">
++      A global interface used for informing the compositor about applications
++      being activated or started, or for applications to request to be
++      activated.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_activation object">
++        Notify the compositor that the xdg_activation object will no longer be
++        used.
++
++        The child objects created via this interface are unaffected and should
++        be destroyed separately.
++      </description>
++    </request>
++
++    <request name="get_activation_token">
++      <description summary="requests a token">
++        Creates an xdg_activation_token_v1 object that will provide
++        the initiating client with a unique token for this activation. This
++        token should be offered to the clients to be activated.
++      </description>
++
++      <arg name="id" type="new_id" interface="xdg_activation_token_v1"/>
++    </request>
++
++    <request name="activate">
++      <description summary="notify new interaction being available">
++        Requests surface activation. It's up to the compositor to display
++        this information as desired, for example by placing the surface above
++        the rest.
++
++        The compositor may know who requested this by checking the activation
++        token and might decide not to follow through with the activation if it's
++        considered unwanted.
++
++        Compositors can ignore unknown activation tokens when an invalid
++        token is passed.
++      </description>
++      <arg name="token" type="string" summary="the activation token of the initiating client"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the wl_surface to activate"/>
++    </request>
++  </interface>
++
++  <interface name="xdg_activation_token_v1" version="1">
++    <description summary="an exported activation handle">
++      An object for setting up a token and receiving a token handle that can
++      be passed as an activation token to another client.
++
++      The object is created using the xdg_activation_v1.get_activation_token
++      request. This object should then be populated with the app_id, surface
++      and serial information and committed. The compositor shall then issue a
++      done event with the token. In case the request's parameters are invalid,
++      the compositor will provide an invalid token.
++    </description>
++
++    <enum name="error">
++      <entry name="already_used" value="0"
++             summary="The token has already been used previously"/>
++    </enum>
++
++    <request name="set_serial">
++      <description summary="specifies the seat and serial of the activating event">
++        Provides information about the seat and serial event that requested the
++        token.
++
++        The serial can come from an input or focus event. For instance, if a
++        click triggers the launch of a third-party client, the launcher client
++        should send a set_serial request with the serial and seat from the
++        wl_pointer.button event.
++
++        Some compositors might refuse to activate toplevels when the token
++        doesn't have a valid and recent enough event serial.
++
++        Must be sent before commit. This information is optional.
++      </description>
++      <arg name="serial" type="uint"
++           summary="the serial of the event that triggered the activation"/>
++      <arg name="seat" type="object" interface="wl_seat"
++           summary="the wl_seat of the event"/>
++    </request>
++
++    <request name="set_app_id">
++      <description summary="specifies the application being activated">
++        The requesting client can specify an app_id to associate the token
++        being created with it.
++
++        Must be sent before commit. This information is optional.
++      </description>
++      <arg name="app_id" type="string"
++           summary="the application id of the client being activated."/>
++    </request>
++
++    <request name="set_surface">
++      <description summary="specifies the surface requesting activation">
++        This request sets the surface requesting the activation. Note, this is
++        different from the surface that will be activated.
++
++        Some compositors might refuse to activate toplevels when the token
++        doesn't have a requesting surface.
++
++        Must be sent before commit. This information is optional.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the requesting surface"/>
++    </request>
++
++    <request name="commit">
++      <description summary="issues the token request">
++        Requests an activation token based on the different parameters that
++        have been offered through set_serial, set_surface and set_app_id.
++      </description>
++    </request>
++
++    <event name="done">
++      <description summary="the exported activation token">
++        The 'done' event contains the unique token of this activation request
++        and notifies that the provider is done.
++      </description>
++      <arg name="token" type="string" summary="the exported activation token"/>
++    </event>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_activation_token_v1 object">
++        Notify the compositor that the xdg_activation_token_v1 object will no
++        longer be used.
++      </description>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..67aeb2be785e3341aff6124a478a1b8b045419c3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++#include "@PROTOCOL_CLIENT_INCLUDE_FILE@"
++#include "@PROTOCOL_SERVER_INCLUDE_FILE@"
++
++/* This is a build-test only */
++
++using namespace std;
++
++int
++main(int argc, char **argv)
++{
++      (void)argc;
++      (void)argv;
++      return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..39b4127d326921f5f6dc44b753e5deaa3b695acf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,12 @@@
++#include "@PROTOCOL_CLIENT_INCLUDE_FILE@"
++#include "@PROTOCOL_SERVER_INCLUDE_FILE@"
++
++/* This is a build-test only */
++
++int
++main(int argc, char **argv)
++{
++      (void)argc;
++      (void)argv;
++      return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2441cce0e33d8a7080ef64eb40caf44162e2e8b4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,145 @@@
++prog_scan_sh = find_program('scan.sh')
++dep_scanner = dependency('wayland-scanner', version: '>=1.20.0', native: true)
++prog_scanner = find_program(dep_scanner.get_variable(pkgconfig: 'wayland_scanner'))
++
++libwayland = [
++      dependency('wayland-client'),
++      dependency('wayland-server'),
++]
++
++# Check that each protocol passes through the scanner
++foreach protocol_file : protocol_files
++      protocol_path = join_paths(wayland_protocols_srcdir, protocol_file)
++      test_name = 'scan-@0@'.format(protocol_file.underscorify())
++      test(test_name, prog_scan_sh,
++              args: protocol_path,
++              env: [
++                      'SCANNER=@0@'.format(prog_scanner.full_path()),
++              ]
++      )
++endforeach
++
++# Check buildability
++
++add_languages('c', 'cpp', native: false)
++replace = find_program('replace.py')
++
++extra_linker_flags = meson.get_compiler('c').get_supported_link_arguments([
++      '-Wl,--unresolved-symbols=ignore-all',
++])
++
++foreach protocol_file : protocol_files
++      xml_file = fs.name(protocol_file)
++      xml_components = xml_file.split('.')
++      protocol_base_file_name = xml_components[0]
++
++      protocol_path = files(join_paths(wayland_protocols_srcdir, protocol_file))
++      client_header_path = '@0@-client.h'.format(protocol_base_file_name)
++      server_header_path = '@0@-server.h'.format(protocol_base_file_name)
++      code_path = '@0@-code.c'.format(protocol_base_file_name)
++      client_header = custom_target(
++              client_header_path,
++              output: client_header_path,
++              input: protocol_path,
++              command: [
++                      prog_scanner,
++                      '--strict',
++                      'client-header',
++                      '@INPUT@',
++                      '@OUTPUT@',
++              ],
++              install: false,
++      )
++      server_header = custom_target(
++              server_header_path,
++              output: server_header_path,
++              input: protocol_path,
++              command: [
++                      prog_scanner,
++                      '--strict',
++                      'server-header',
++                      '@INPUT@',
++                      '@OUTPUT@',
++              ],
++              install: false,
++      )
++      code = custom_target(
++              code_path,
++              output: code_path,
++              input: protocol_path,
++              command: [
++                      prog_scanner,
++                      '--strict',
++                      'private-code',
++                      '@INPUT@',
++                      '@OUTPUT@',
++              ],
++              install: false,
++      )
++
++      replace_command = [
++              replace,
++              '@INPUT@',
++              '@OUTPUT@',
++              'PROTOCOL_CLIENT_INCLUDE_FILE',
++              client_header.full_path(),
++              'PROTOCOL_SERVER_INCLUDE_FILE',
++              server_header.full_path(),
++      ]
++
++      # Check that header can be included by a pedantic C99 compiler
++      test_name = 'test-build-pedantic-@0@'.format(protocol_file.underscorify())
++      test_name_source = '@0@.c'.format(test_name)
++      test_source = custom_target(
++              test_name_source,
++              input: 'build-pedantic.c.in',
++              output: test_name_source,
++              command: replace_command,
++      )
++      pedantic_test_executable = executable(
++              test_name,
++              [
++                      test_source,
++                      client_header,
++                      server_header,
++                      code
++              ],
++              link_args: extra_linker_flags,
++              dependencies: libwayland,
++              c_args: [
++                      '-std=c99',
++                      '-pedantic',
++                      '-Wall',
++                      '-Werror' ],
++              install: false,
++      )
++      test(test_name, pedantic_test_executable)
++
++      # Check that the header
++      if not protocol_file.contains('xdg-foreign-unstable-v1')
++              test_name = 'test-build-cxx-@0@'.format(protocol_file.underscorify())
++              test_name_source = '@0@.cc'.format(test_name)
++              test_source = custom_target(
++                      test_name_source,
++                      input: 'build-cxx.cc.in',
++                      output: test_name_source,
++                      command: replace_command,
++              )
++              cxx_test_executable = executable(
++                      test_name,
++                      [
++                              test_source,
++                              client_header,
++                              server_header,
++                      ],
++                      link_args: extra_linker_flags,
++                      dependencies: libwayland,
++                      cpp_args: [
++                              '-Wall',
++                              '-Werror',
++                      ],
++                      install: false,
++              )
++              test(test_name, cxx_test_executable)
++      endif
++endforeach
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0ab7dfdada9690cbc9f20097b690e9301041f21e
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,23 @@@
++#!/usr/bin/env python3
++
++import sys
++
++execpath, inpath, outpath, *dict_list = sys.argv
++
++dictonary = {}
++while dict_list:
++    key, value, *rest = dict_list
++    dictonary[key] = value
++    dict_list = rest
++
++infile = open(inpath, 'r')
++outfile = open(outpath, 'w')
++
++buf = infile.read()
++infile.close()
++
++for key, value in dictonary.items():
++    buf = buf.replace('@{}@'.format(key), value)
++
++outfile.write(buf)
++outfile.close()
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cad688775909058e6386da56f04dea5b8577c162
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,11 @@@
++#!/bin/sh -e
++
++if [ "x$SCANNER" = "x" ] ; then
++      echo "No scanner present, test skipped." 1>&2
++      exit 77
++fi
++
++$SCANNER client-header --strict $1 /dev/null
++$SCANNER server-header --strict $1 /dev/null
++$SCANNER private-code --strict $1 /dev/null
++$SCANNER public-code --strict $1 /dev/null
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5ad740f5e79880599567ac3a15145157aafdc5e3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Fullscreen shell protocol
++
++Maintainers:
++Jason Ekstrand <jason@jlekstrand.net>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..db70f09e72ff063f4851b28ac12389b97f3c09bb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,254 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="fullscreen_shell_unstable_v1">
++
++  <copyright>
++    Copyright © 2016 Yong Bakos
++    Copyright © 2015 Jason Ekstrand
++    Copyright © 2015 Jonas Ådahl
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_fullscreen_shell_v1" version="1">
++    <description summary="displays a single surface per output">
++      Displays a single surface per output.
++
++      This interface provides a mechanism for a single client to display
++      simple full-screen surfaces.  While there technically may be multiple
++      clients bound to this interface, only one of those clients should be
++      shown at a time.
++
++      To present a surface, the client uses either the present_surface or
++      present_surface_for_mode requests.  Presenting a surface takes effect
++      on the next wl_surface.commit.  See the individual requests for
++      details about scaling and mode switches.
++
++      The client can have at most one surface per output at any time.
++      Requesting a surface to be presented on an output that already has a
++      surface replaces the previously presented surface.  Presenting a null
++      surface removes its content and effectively disables the output.
++      Exactly what happens when an output is "disabled" is
++      compositor-specific.  The same surface may be presented on multiple
++      outputs simultaneously.
++
++      Once a surface is presented on an output, it stays on that output
++      until either the client removes it or the compositor destroys the
++      output.  This way, the client can update the output's contents by
++      simply attaching a new buffer.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="release" type="destructor">
++      <description summary="release the wl_fullscreen_shell interface">
++      Release the binding from the wl_fullscreen_shell interface.
++
++      This destroys the server-side object and frees this binding.  If
++      the client binds to wl_fullscreen_shell multiple times, it may wish
++      to free some of those bindings.
++      </description>
++    </request>
++
++    <enum name="capability">
++      <description summary="capabilities advertised by the compositor">
++      Various capabilities that can be advertised by the compositor.  They
++      are advertised one-at-a-time when the wl_fullscreen_shell interface is
++      bound.  See the wl_fullscreen_shell.capability event for more details.
++
++      ARBITRARY_MODES:
++      This is a hint to the client that indicates that the compositor is
++      capable of setting practically any mode on its outputs.  If this
++      capability is provided, wl_fullscreen_shell.present_surface_for_mode
++      will almost never fail and clients should feel free to set whatever
++      mode they like.  If the compositor does not advertise this, it may
++      still support some modes that are not advertised through wl_global.mode
++      but it is less likely.
++
++      CURSOR_PLANE:
++      This is a hint to the client that indicates that the compositor can
++      handle a cursor surface from the client without actually compositing.
++      This may be because of a hardware cursor plane or some other mechanism.
++      If the compositor does not advertise this capability then setting
++      wl_pointer.cursor may degrade performance or be ignored entirely.  If
++      CURSOR_PLANE is not advertised, it is recommended that the client draw
++      its own cursor and set wl_pointer.cursor(NULL).
++      </description>
++      <entry name="arbitrary_modes" value="1" summary="compositor is capable of almost any output mode"/>
++      <entry name="cursor_plane" value="2" summary="compositor has a separate cursor plane"/>
++    </enum>
++
++    <event name="capability">
++      <description summary="advertises a capability of the compositor">
++      Advertises a single capability of the compositor.
++
++      When the wl_fullscreen_shell interface is bound, this event is emitted
++      once for each capability advertised.  Valid capabilities are given by
++      the wl_fullscreen_shell.capability enum.  If clients want to take
++      advantage of any of these capabilities, they should use a
++      wl_display.sync request immediately after binding to ensure that they
++      receive all the capability events.
++      </description>
++      <arg name="capability" type="uint" enum="capability" />
++    </event>
++
++    <enum name="present_method">
++      <description summary="different method to set the surface fullscreen">
++      Hints to indicate to the compositor how to deal with a conflict
++      between the dimensions of the surface and the dimensions of the
++      output. The compositor is free to ignore this parameter.
++      </description>
++      <entry name="default" value="0" summary="no preference, apply default policy"/>
++      <entry name="center" value="1" summary="center the surface on the output"/>
++      <entry name="zoom" value="2" summary="scale the surface, preserving aspect ratio, to the largest size that will fit on the output" />
++      <entry name="zoom_crop" value="3" summary="scale the surface, preserving aspect ratio, to fully fill the output cropping if needed" />
++      <entry name="stretch" value="4" summary="scale the surface to the size of the output ignoring aspect ratio" />
++    </enum>
++
++    <request name="present_surface">
++      <description summary="present surface for display">
++      Present a surface on the given output.
++
++      If the output is null, the compositor will present the surface on
++      whatever display (or displays) it thinks best.  In particular, this
++      may replace any or all surfaces currently presented so it should
++      not be used in combination with placing surfaces on specific
++      outputs.
++
++      The method parameter is a hint to the compositor for how the surface
++      is to be presented.  In particular, it tells the compositor how to
++      handle a size mismatch between the presented surface and the
++      output.  The compositor is free to ignore this parameter.
++
++      The "zoom", "zoom_crop", and "stretch" methods imply a scaling
++      operation on the surface.  This will override any kind of output
++      scaling, so the buffer_scale property of the surface is effectively
++      ignored.
++
++      This request gives the surface the role of a fullscreen shell surface.
++      If the surface already has another role, it raises a role protocol
++      error.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++      <arg name="method" type="uint" enum="present_method" />
++      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++    </request>
++
++    <request name="present_surface_for_mode">
++      <description summary="present surface for display at a particular mode">
++      Presents a surface on the given output for a particular mode.
++
++      If the current size of the output differs from that of the surface,
++      the compositor will attempt to change the size of the output to
++      match the surface.  The result of the mode-switch operation will be
++      returned via the provided wl_fullscreen_shell_mode_feedback object.
++
++      If the current output mode matches the one requested or if the
++      compositor successfully switches the mode to match the surface,
++      then the mode_successful event will be sent and the output will
++      contain the contents of the given surface.  If the compositor
++      cannot match the output size to the surface size, the mode_failed
++      will be sent and the output will contain the contents of the
++      previously presented surface (if any).  If another surface is
++      presented on the given output before either of these has a chance
++      to happen, the present_cancelled event will be sent.
++
++      Due to race conditions and other issues unknown to the client, no
++      mode-switch operation is guaranteed to succeed.  However, if the
++      mode is one advertised by wl_output.mode or if the compositor
++      advertises the ARBITRARY_MODES capability, then the client should
++      expect that the mode-switch operation will usually succeed.
++
++      If the size of the presented surface changes, the resulting output
++      is undefined.  The compositor may attempt to change the output mode
++      to compensate.  However, there is no guarantee that a suitable mode
++      will be found and the client has no way to be notified of success
++      or failure.
++
++      The framerate parameter specifies the desired framerate for the
++      output in mHz.  The compositor is free to ignore this parameter.  A
++      value of 0 indicates that the client has no preference.
++
++      If the value of wl_output.scale differs from wl_surface.buffer_scale,
++      then the compositor may choose a mode that matches either the buffer
++      size or the surface size.  In either case, the surface will fill the
++      output.
++
++      This request gives the surface the role of a fullscreen shell surface.
++      If the surface already has another role, it raises a role protocol
++      error.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="output" type="object" interface="wl_output"/>
++      <arg name="framerate" type="int"/>
++      <arg name="feedback" type="new_id" interface="zwp_fullscreen_shell_mode_feedback_v1"/>
++    </request>
++
++    <enum name="error">
++      <description summary="wl_fullscreen_shell error values">
++      These errors can be emitted in response to wl_fullscreen_shell requests.
++      </description>
++      <entry name="invalid_method" value="0" summary="present_method is not known"/>
++      <entry name="role" value="1" summary="given wl_surface has another role"/>
++    </enum>
++  </interface>
++
++  <interface name="zwp_fullscreen_shell_mode_feedback_v1" version="1">
++    <event name="mode_successful" type="destructor">
++      <description summary="mode switch succeeded">
++      This event indicates that the attempted mode switch operation was
++      successful.  A surface of the size requested in the mode switch
++      will fill the output without scaling.
++
++      Upon receiving this event, the client should destroy the
++      wl_fullscreen_shell_mode_feedback object.
++      </description>
++    </event>
++
++    <event name="mode_failed" type="destructor">
++      <description summary="mode switch failed">
++      This event indicates that the attempted mode switch operation
++      failed.  This may be because the requested output mode is not
++      possible or it may mean that the compositor does not want to allow it.
++
++      Upon receiving this event, the client should destroy the
++      wl_fullscreen_shell_mode_feedback object.
++      </description>
++    </event>
++
++    <event name="present_cancelled" type="destructor">
++      <description summary="mode switch cancelled">
++      This event indicates that the attempted mode switch operation was
++      cancelled.  Most likely this is because the client requested a
++      second mode switch before the first one completed.
++
++      Upon receiving this event, the client should destroy the
++      wl_fullscreen_shell_mode_feedback object.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..396e871626932970b058f0f25ad5d7da6aa03da4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Screensaver inhibition protocol
++
++Maintainers:
++Bryce Harrington <bryce@osg.samsung.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9c06cdcba6c06f978ac81ab70ad4b3f77911c4a4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,83 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="idle_inhibit_unstable_v1">
++
++  <copyright>
++    Copyright © 2015 Samsung Electronics Co., Ltd
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_idle_inhibit_manager_v1" version="1">
++    <description summary="control behavior when display idles">
++      This interface permits inhibiting the idle behavior such as screen
++      blanking, locking, and screensaving.  The client binds the idle manager
++      globally, then creates idle-inhibitor objects for each surface.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the idle inhibitor object">
++      Destroy the inhibit manager.
++      </description>
++    </request>
++
++    <request name="create_inhibitor">
++      <description summary="create a new inhibitor object">
++      Create a new inhibitor object associated with the given surface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_idle_inhibitor_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface that inhibits the idle behavior"/>
++    </request>
++
++  </interface>
++
++  <interface name="zwp_idle_inhibitor_v1" version="1">
++    <description summary="context object for inhibiting idle behavior">
++      An idle inhibitor prevents the output that the associated surface is
++      visible on from being set to a state where it is not visually usable due
++      to lack of user interaction (e.g. blanked, dimmed, locked, set to power
++      save, etc.)  Any screensaver processes are also blocked from displaying.
++
++      If the surface is destroyed, unmapped, becomes occluded, loses
++      visibility, or otherwise becomes not visually relevant for the user, the
++      idle inhibitor will not be honored by the compositor; if the surface
++      subsequently regains visibility the inhibitor takes effect once again.
++      Likewise, the inhibitor isn't honored if the system was already idled at
++      the time the inhibitor was established, although if the system later
++      de-idles and re-idles the inhibitor will take effect.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the idle inhibitor object">
++      Remove the inhibitor effect from the associated wl_surface.
++      </description>
++    </request>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c95ba72789b93fb8afbf6086932c81e3dcf7f60c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Input method protocol
++
++Maintainers:
++Jan Arne Petersen <janarne@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e9d93ba609efab7dae93d485caa2d3c787478033
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,305 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="input_method_unstable_v1">
++
++  <copyright>
++    Copyright © 2012, 2013 Intel Corporation
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_input_method_context_v1" version="1">
++    <description summary="input method context">
++      Corresponds to a text input on the input method side. An input method context
++      is created on text input activation on the input method side. It allows
++      receiving information about the text input from the application via events.
++      Input method contexts do not keep state after deactivation and should be
++      destroyed after deactivation is handled.
++
++      Text is generally UTF-8 encoded, indices and lengths are in bytes.
++
++      Serials are used to synchronize the state between the text input and
++      an input method. New serials are sent by the text input in the
++      commit_state request and are used by the input method to indicate
++      the known text input state in events like preedit_string, commit_string,
++      and keysym. The text input can then ignore events from the input method
++      which are based on an outdated state (for example after a reset).
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="destroy" type="destructor"/>
++
++    <request name="commit_string">
++      <description summary="commit string">
++      Send the commit string text for insertion to the application.
++
++      The text to commit could be either just a single character after a key
++      press or the result of some composing (pre-edit). It could be also an
++      empty text when some text should be removed (see
++      delete_surrounding_text) or when the input cursor should be moved (see
++      cursor_position).
++
++      Any previously set composing text will be removed.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="text" type="string"/>
++    </request>
++
++    <request name="preedit_string">
++      <description summary="pre-edit string">
++      Send the pre-edit string text to the application text input.
++
++      The commit text can be used to replace the pre-edit text on reset (for
++      example on unfocus).
++
++      Previously sent preedit_style and preedit_cursor requests are also
++      processed by the text_input.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="text" type="string"/>
++      <arg name="commit" type="string"/>
++    </request>
++
++    <request name="preedit_styling">
++      <description summary="pre-edit styling">
++      Set the styling information on composing text. The style is applied for
++      length in bytes from index relative to the beginning of
++      the composing text (as byte offset). Multiple styles can
++      be applied to a composing text.
++
++      This request should be sent before sending a preedit_string request.
++      </description>
++      <arg name="index" type="uint"/>
++      <arg name="length" type="uint"/>
++      <arg name="style" type="uint"/>
++    </request>
++
++    <request name="preedit_cursor">
++      <description summary="pre-edit cursor">
++      Set the cursor position inside the composing text (as byte offset)
++      relative to the start of the composing text.
++
++      When index is negative no cursor should be displayed.
++
++      This request should be sent before sending a preedit_string request.
++      </description>
++      <arg name="index" type="int"/>
++    </request>
++
++    <request name="delete_surrounding_text">
++      <description summary="delete text">
++      Remove the surrounding text.
++
++      This request will be handled on the text_input side directly following
++      a commit_string request.
++      </description>
++      <arg name="index" type="int"/>
++      <arg name="length" type="uint"/>
++    </request>
++
++    <request name="cursor_position">
++      <description summary="set cursor to a new position">
++      Set the cursor and anchor to a new position. Index is the new cursor
++      position in bytes (when >= 0 this is relative to the end of the inserted text,
++      otherwise it is relative to the beginning of the inserted text). Anchor is
++      the new anchor position in bytes (when >= 0 this is relative to the end of the
++      inserted text, otherwise it is relative to the beginning of the inserted
++      text). When there should be no selected text, anchor should be the same
++      as index.
++
++      This request will be handled on the text_input side directly following
++      a commit_string request.
++      </description>
++      <arg name="index" type="int"/>
++      <arg name="anchor" type="int"/>
++    </request>
++
++    <request name="modifiers_map">
++      <arg name="map" type="array"/>
++    </request>
++
++    <request name="keysym">
++      <description summary="keysym">
++      Notify when a key event was sent. Key events should not be used for
++      normal text input operations, which should be done with commit_string,
++      delete_surrounding_text, etc. The key event follows the wl_keyboard key
++      event convention. Sym is an XKB keysym, state is a wl_keyboard key_state.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="time" type="uint"/>
++      <arg name="sym" type="uint"/>
++      <arg name="state" type="uint"/>
++      <arg name="modifiers" type="uint"/>
++    </request>
++
++    <request name="grab_keyboard">
++      <description summary="grab hardware keyboard">
++      Allow an input method to receive hardware keyboard input and process
++      key events to generate text events (with pre-edit) over the wire. This
++      allows input methods which compose multiple key events for inputting
++      text like it is done for CJK languages.
++      </description>
++      <arg name="keyboard" type="new_id" interface="wl_keyboard"/>
++    </request>
++
++    <request name="key">
++      <description summary="forward key event">
++      Forward a wl_keyboard::key event to the client that was not processed
++      by the input method itself. Should be used when filtering key events
++      with grab_keyboard.  The arguments should be the ones from the
++      wl_keyboard::key event.
++
++      For generating custom key events use the keysym request instead.
++      </description>
++      <arg name="serial" type="uint" summary="serial from wl_keyboard::key"/>
++      <arg name="time" type="uint" summary="time from wl_keyboard::key"/>
++      <arg name="key" type="uint" summary="key from wl_keyboard::key"/>
++      <arg name="state" type="uint" summary="state from wl_keyboard::key"/>
++    </request>
++
++    <request name="modifiers">
++      <description summary="forward modifiers event">
++      Forward a wl_keyboard::modifiers event to the client that was not
++      processed by the input method itself.  Should be used when filtering
++      key events with grab_keyboard. The arguments should be the ones
++      from the wl_keyboard::modifiers event.
++      </description>
++      <arg name="serial" type="uint" summary="serial from wl_keyboard::modifiers"/>
++      <arg name="mods_depressed" type="uint" summary="mods_depressed from wl_keyboard::modifiers"/>
++      <arg name="mods_latched" type="uint" summary="mods_latched from wl_keyboard::modifiers"/>
++      <arg name="mods_locked" type="uint" summary="mods_locked from wl_keyboard::modifiers"/>
++      <arg name="group" type="uint" summary="group from wl_keyboard::modifiers"/>
++    </request>
++
++    <request name="language">
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="language" type="string"/>
++    </request>
++
++    <request name="text_direction">
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="direction" type="uint"/>
++    </request>
++
++    <event name="surrounding_text">
++      <description summary="surrounding text event">
++      The plain surrounding text around the input position. Cursor is the
++      position in bytes within the surrounding text relative to the beginning
++      of the text. Anchor is the position in bytes of the selection anchor
++      within the surrounding text relative to the beginning of the text. If
++      there is no selected text then anchor is the same as cursor.
++      </description>
++      <arg name="text" type="string"/>
++      <arg name="cursor" type="uint"/>
++      <arg name="anchor" type="uint"/>
++    </event>
++
++    <event name="reset">
++    </event>
++
++    <event name="content_type">
++      <arg name="hint" type="uint"/>
++      <arg name="purpose" type="uint"/>
++    </event>
++
++    <event name="invoke_action">
++      <arg name="button" type="uint"/>
++      <arg name="index" type="uint"/>
++    </event>
++
++    <event name="commit_state">
++      <arg name="serial" type="uint" summary="serial of text input state"/>
++    </event>
++
++    <event name="preferred_language">
++      <arg name="language" type="string"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_input_method_v1" version="1">
++    <description summary="input method">
++      An input method object is responsible for composing text in response to
++      input from hardware or virtual keyboards. There is one input method
++      object per seat. On activate there is a new input method context object
++      created which allows the input method to communicate with the text input.
++    </description>
++
++    <event name="activate">
++      <description summary="activate event">
++      A text input was activated. Creates an input method context object
++      which allows communication with the text input.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_input_method_context_v1"/>
++    </event>
++
++    <event name="deactivate">
++      <description summary="deactivate event">
++      The text input corresponding to the context argument was deactivated.
++      The input method context should be destroyed after deactivation is
++      handled.
++      </description>
++      <arg name="context" type="object" interface="zwp_input_method_context_v1"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_input_panel_v1" version="1">
++    <description summary="interface for implementing keyboards">
++      Only one client can bind this interface at a time.
++    </description>
++
++    <request name="get_input_panel_surface">
++      <arg name="id" type="new_id" interface="zwp_input_panel_surface_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_input_panel_surface_v1" version="1">
++    <enum name="position">
++      <entry name="center_bottom" value="0"/>
++    </enum>
++
++    <request name="set_toplevel">
++      <description summary="set the surface type as a keyboard">
++      Set the input_panel_surface type to keyboard.
++
++      A keyboard surface is only shown when a text input is active.
++      </description>
++      <arg name="output" type="object" interface="wl_output"/>
++      <arg name="position" type="uint"/>
++    </request>
++
++    <request name="set_overlay_panel">
++      <description summary="set the surface type as an overlay panel">
++      Set the input_panel_surface to be an overlay panel.
++
++      This is shown near the input cursor above the application window when
++      a text input is active.
++      </description>
++    </request>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3e82890bb3d1bb535d37fcc6ab69ba00c0c222f2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++High-resolution timestamps for input events.
++
++Maintainers:
++Alexandros Frantzis <alexandros.frantzis@collabora.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7c5e08280af52da3c73326216c6c8cd730a4573e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,145 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="input_timestamps_unstable_v1">
++
++  <copyright>
++    Copyright © 2017 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="High-resolution timestamps for input events">
++    This protocol specifies a way for a client to request and receive
++    high-resolution timestamps for input events.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible changes
++    may be added together with the corresponding interface version bump.
++    Backward incompatible changes are done by bumping the version number in
++    the protocol and interface names and resetting the interface version.
++    Once the protocol is to be declared stable, the 'z' prefix and the
++    version number in the protocol and interface names are removed and the
++    interface version number is reset.
++  </description>
++
++  <interface name="zwp_input_timestamps_manager_v1" version="1">
++    <description summary="context object for high-resolution input timestamps">
++      A global interface used for requesting high-resolution timestamps
++      for input events.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the input timestamps manager object">
++        Informs the server that the client will no longer be using this
++        protocol object. Existing objects created by this object are not
++        affected.
++      </description>
++    </request>
++
++    <request name="get_keyboard_timestamps">
++      <description summary="subscribe to high-resolution keyboard timestamp events">
++        Creates a new input timestamps object that represents a subscription
++        to high-resolution timestamp events for all wl_keyboard events that
++        carry a timestamp.
++
++        If the associated wl_keyboard object is invalidated, either through
++        client action (e.g. release) or server-side changes, the input
++        timestamps object becomes inert and the client should destroy it
++        by calling zwp_input_timestamps_v1.destroy.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++      <arg name="keyboard" type="object" interface="wl_keyboard"
++           summary="the wl_keyboard object for which to get timestamp events"/>
++    </request>
++
++    <request name="get_pointer_timestamps">
++      <description summary="subscribe to high-resolution pointer timestamp events">
++        Creates a new input timestamps object that represents a subscription
++        to high-resolution timestamp events for all wl_pointer events that
++        carry a timestamp.
++
++        If the associated wl_pointer object is invalidated, either through
++        client action (e.g. release) or server-side changes, the input
++        timestamps object becomes inert and the client should destroy it
++        by calling zwp_input_timestamps_v1.destroy.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++      <arg name="pointer" type="object" interface="wl_pointer"
++           summary="the wl_pointer object for which to get timestamp events"/>
++    </request>
++
++    <request name="get_touch_timestamps">
++      <description summary="subscribe to high-resolution touch timestamp events">
++        Creates a new input timestamps object that represents a subscription
++        to high-resolution timestamp events for all wl_touch events that
++        carry a timestamp.
++
++        If the associated wl_touch object becomes invalid, either through
++        client action (e.g. release) or server-side changes, the input
++        timestamps object becomes inert and the client should destroy it
++        by calling zwp_input_timestamps_v1.destroy.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_input_timestamps_v1"/>
++      <arg name="touch" type="object" interface="wl_touch"
++           summary="the wl_touch object for which to get timestamp events"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_input_timestamps_v1" version="1">
++    <description summary="context object for input timestamps">
++      Provides high-resolution timestamp events for a set of subscribed input
++      events. The set of subscribed input events is determined by the
++      zwp_input_timestamps_manager_v1 request used to create this object.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the input timestamps object">
++        Informs the server that the client will no longer be using this
++        protocol object. After the server processes the request, no more
++        timestamp events will be emitted.
++      </description>
++    </request>
++
++    <event name="timestamp">
++      <description summary="high-resolution timestamp event">
++        The timestamp event is associated with the first subsequent input event
++        carrying a timestamp which belongs to the set of input events this
++        object is subscribed to.
++
++        The timestamp provided by this event is a high-resolution version of
++        the timestamp argument of the associated input event. The provided
++        timestamp is in the same clock domain and is at least as accurate as
++        the associated input event timestamp.
++
++        The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples,
++        each component being an unsigned 32-bit value. Whole seconds are in
++        tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo,
++        and the additional fractional part in tv_nsec as nanoseconds. Hence,
++        for valid timestamps tv_nsec must be in [0, 999999999].
++      </description>
++      <arg name="tv_sec_hi" type="uint"
++           summary="high 32 bits of the seconds part of the timestamp"/>
++      <arg name="tv_sec_lo" type="uint"
++           summary="low 32 bits of the seconds part of the timestamp"/>
++      <arg name="tv_nsec" type="uint"
++           summary="nanoseconds part of the timestamp"/>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..63ff3350a28c8e3c009d01dddbbc4fba6724dcd2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Compositor shortcuts inhibit protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..27748764d835daeceb5ff76882783a45878638e5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,143 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="keyboard_shortcuts_inhibit_unstable_v1">
++
++  <copyright>
++    Copyright © 2017 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for inhibiting the compositor keyboard shortcuts">
++    This protocol specifies a way for a client to request the compositor
++    to ignore its own keyboard shortcuts for a given seat, so that all
++    key events from that seat get forwarded to a surface.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible
++    changes may be added together with the corresponding interface
++    version bump.
++    Backward incompatible changes are done by bumping the version
++    number in the protocol and interface names and resetting the
++    interface version. Once the protocol is to be declared stable,
++    the 'z' prefix and the version number in the protocol and
++    interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zwp_keyboard_shortcuts_inhibit_manager_v1" version="1">
++    <description summary="context object for keyboard grab_manager">
++      A global interface used for inhibiting the compositor keyboard shortcuts.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the keyboard shortcuts inhibitor object">
++      Destroy the keyboard shortcuts inhibitor manager.
++      </description>
++    </request>
++
++    <request name="inhibit_shortcuts">
++      <description summary="create a new keyboard shortcuts inhibitor object">
++      Create a new keyboard shortcuts inhibitor object associated with
++      the given surface for the given seat.
++
++      If shortcuts are already inhibited for the specified seat and surface,
++      a protocol error "already_inhibited" is raised by the compositor.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_keyboard_shortcuts_inhibitor_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface that inhibits the keyboard shortcuts behavior"/>
++      <arg name="seat" type="object" interface="wl_seat"
++         summary="the wl_seat for which keyboard shortcuts should be disabled"/>
++    </request>
++
++    <enum name="error">
++      <entry name="already_inhibited"
++           value="0"
++           summary="the shortcuts are already inhibited for this surface"/>
++    </enum>
++  </interface>
++
++  <interface name="zwp_keyboard_shortcuts_inhibitor_v1" version="1">
++    <description summary="context object for keyboard shortcuts inhibitor">
++      A keyboard shortcuts inhibitor instructs the compositor to ignore
++      its own keyboard shortcuts when the associated surface has keyboard
++      focus. As a result, when the surface has keyboard focus on the given
++      seat, it will receive all key events originating from the specified
++      seat, even those which would normally be caught by the compositor for
++      its own shortcuts.
++
++      The Wayland compositor is however under no obligation to disable
++      all of its shortcuts, and may keep some special key combo for its own
++      use, including but not limited to one allowing the user to forcibly
++      restore normal keyboard events routing in the case of an unwilling
++      client. The compositor may also use the same key combo to reactivate
++      an existing shortcut inhibitor that was previously deactivated on
++      user request.
++
++      When the compositor restores its own keyboard shortcuts, an
++      "inactive" event is emitted to notify the client that the keyboard
++      shortcuts inhibitor is not effectively active for the surface and
++      seat any more, and the client should not expect to receive all
++      keyboard events.
++
++      When the keyboard shortcuts inhibitor is inactive, the client has
++      no way to forcibly reactivate the keyboard shortcuts inhibitor.
++
++      The user can chose to re-enable a previously deactivated keyboard
++      shortcuts inhibitor using any mechanism the compositor may offer,
++      in which case the compositor will send an "active" event to notify
++      the client.
++
++      If the surface is destroyed, unmapped, or loses the seat's keyboard
++      focus, the keyboard shortcuts inhibitor becomes irrelevant and the
++      compositor will restore its own keyboard shortcuts but no "inactive"
++      event is emitted in this case.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the keyboard shortcuts inhibitor object">
++      Remove the keyboard shortcuts inhibitor from the associated wl_surface.
++      </description>
++    </request>
++
++    <event name="active">
++      <description summary="shortcuts are inhibited">
++      This event indicates that the shortcut inhibitor is active.
++
++      The compositor sends this event every time compositor shortcuts
++      are inhibited on behalf of the surface. When active, the client
++      may receive input events normally reserved by the compositor
++      (see zwp_keyboard_shortcuts_inhibitor_v1).
++
++      This occurs typically when the initial request "inhibit_shortcuts"
++      first becomes active or when the user instructs the compositor to
++      re-enable and existing shortcuts inhibitor using any mechanism
++      offered by the compositor.
++      </description>
++    </event>
++
++    <event name="inactive">
++      <description summary="shortcuts are restored">
++      This event indicates that the shortcuts inhibitor is inactive,
++      normal shortcuts processing is restored by the compositor.
++       </description>
++    </event>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cdedf98a5a8fff43e5ec8cf5f5e9f6ec8d03c682
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++Linux DMA-BUF protocol
++
++Maintainers:
++Pekka Paalanen <pekka.paalanen@collabora.co.uk>
++Daniel Stone <daniels@collabora.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a3f94ed456db6a755adbf661f4d80bc2684842c6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,218 @@@
++.. Copyright 2021 Simon Ser
++
++.. contents::
++
++
++linux-dmabuf feedback introduction
++==================================
++
++linux-dmabuf feedback allows compositors and clients to negotiate optimal buffer
++allocation parameters. This document will assume that the compositor is using a
++rendering API such as OpenGL or Vulkan and KMS as the presentation API: even if
++linux-dmabuf feedback isn't restricted to this use-case, it's the most common.
++
++linux-dmabuf feedback introduces the following concepts:
++
++1. A main device. This is the render device that the compositor is using to
++   perform composition. Compositors should always be able to display a buffer
++   submitted by a client, so this device can be used as a fallback in case none
++   of the more optimized code-paths work. Clients should allocate buffers such
++   that they can be imported and textured from the main device.
++
++2. One or more tranches. Each tranche consists of a target device, allocation
++   flags and a set of format/modifier pairs. A tranche can be seen as a set of
++   formats/modifier pairs that are compatible with the target device.
++
++   A tranche can have the ``scanout`` flag. It means that the target device is
++   a KMS device, and that buffers allocated with one of the format/modifier
++   pairs in the tranche are eligible for direct scanout.
++
++   Clients should use the tranches in order to allocate buffers with the most
++   appropriate format/modifier and also to avoid allocating in private device
++   memory when cross-device operations are going to happen.
++
++linux-dmabuf feedback implementation notes
++==========================================
++
++This section contains recommendations for client and compositor implementations.
++
++For clients
++-----------
++
++Clients are expected to either pick a fixed DRM format beforehand, or
++perform the following steps repeatedly until they find a suitable format.
++
++Basic clients may only support static buffer allocation on startup. These
++clients should do the following:
++
++1. Send a ``get_default_feedback`` request to get global feedback.
++2. Select the device indicated by ``main_device`` for allocation.
++3. For each tranche:
++
++   1. If ``tranche_target_device`` doesn't match the allocation device, ignore
++      the tranche.
++   2. Accumulate allocation flags from ``tranche_flags``.
++   3. Accumulate format/modifier pairs received via ``tranche_formats`` in a
++      list.
++   4. When the ``tranche_done`` event is received, try to allocate the buffer
++      with the accumulated list of modifiers and allocation flags. If that
++      fails, proceed with the next tranche. If that succeeds, stop the loop.
++
++4. Destroy the feedback object.
++
++Tranches are ordered by preference: the more optimized tranches come first. As
++such, clients should use the first tranche that happens to work.
++
++Some clients may have already selected the device they want to use beforehand.
++These clients can ignore the ``main_device`` event, and ignore tranches whose
++``tranche_target_device`` doesn't match the selected device. Such clients need
++to be prepared for the ``wp_linux_buffer_params.create`` request to potentially
++fail.
++
++If the client allocates a buffer without specifying explicit modifiers on a
++device different from the one indicated by ``main_device``, then the client
++must force a linear layout.
++
++Some clients might support re-negotiating the buffer format/modifier on the
++fly. These clients should send a ``get_surface_feedback`` request and keep the
++feedback object alive after the initial allocation. Each time a new set of
++feedback parameters is received (ended by the ``done`` event), they should
++perform the same steps as basic clients described above. They should detect
++when the optimal allocation parameters didn't change (same
++format/modifier/flags) to avoid needlessly re-allocating their buffers.
++
++Some clients might additionally support switching the device used for
++allocations on the fly. Such clients should send a ``get_surface_feedback``
++request. For each tranche, select the device indicated by
++``tranche_target_device`` for allocation. Accumulate allocation flags (received
++via ``tranche_flags``) and format/modifier pairs (received via
++``tranche_formats``) as usual. When the ``tranche_done`` event is received, try
++to allocate the buffer with the accumulated list of modifiers and the
++allocation flags. Try to import the resulting buffer by sending a
++``wp_linux_buffer_params.create`` request (this might fail). Repeat with each
++tranche until an allocation and import succeeds. Each time a new set of
++feedback parameters is received, they should perform these steps again. They
++should detect when the optimal allocation parameters didn't change (same
++device/format/modifier/flags) to avoid needlessly re-allocating their buffers.
++
++For compositors
++---------------
++
++Basic compositors may only support texturing the DMA-BUFs via a rendering API
++such as OpenGL or Vulkan. Such compositors can send a single tranche as a reply
++to both ``get_default_feedback`` and ``get_surface_feedback``. Set the
++``main_device`` to the rendering device. Send the tranche with
++``tranche_target_device`` set to the rendering device and all of the DRM
++format/modifier pairs supported by the rendering API. Do not set the
++``scanout`` flag in the ``tranche_flags`` event.
++
++Some compositors may support direct scan-out for full-screen surfaces. These
++compositors can re-send the feedback parameters when a surface becomes
++full-screen or leaves full-screen mode if the client has used the
++``get_surface_feedback`` request. The non-full-screen feedback parameters are
++the same as basic compositors described above. The full-screen feedback
++parameters have two tranches: one with the format/modifier pairs supported by
++the KMS plane, with the ``scanout`` flag set in the ``tranche_flags`` event and
++with ``tranche_target_device`` set to the KMS scan-out device; the other with
++the rest of the format/modifier pairs (supported for texturing, but not for
++scan-out), without the ``scanout`` flag set in the ``tranche_flags`` event, and
++with the ``tranche_target_device`` set to the rendering device.
++
++Some compositors may support direct scan-out for all surfaces. These
++compositors can send two tranches for surfaces that become candidates for
++direct scan-out, similarly to compositors supporting direct scan-out for
++fullscreen surfaces. When a surface stops being a candidate for direct
++scan-out, compositors should re-send the feedback parameters optimized for
++texturing only.  The way candidates for direct scan-out are selected is
++compositor policy, a possible implementation is to select as many surfaces as
++there are available hardware planes, starting from surfaces closer to the eye.
++
++Some compositors may support multiple devices at the same time. If the
++compositor supports rendering with a fixed device and direct scan-out on a
++secondary device, it may send a separate tranche for surfaces displayed on
++the secondary device that are candidates for direct scan-out. The
++``tranche_target_device`` for this tranche will be the secondary device and
++will not match the ``main_device``.
++
++Some compositors may support switching their rendering device at runtime or
++changing their rendering device depending on the surface. When the rendering
++device changes for a surface, such compositors may re-send the feedback
++parameters with a different ``main_device``. However there is a risk that
++clients don't support switching their device at runtime and continue using the
++previous device. For this reason, compositors should always have a fallback
++rendering device that they initially send as ``main_device``, such that these
++clients use said fallback device.
++
++Compositors should not change the ``main_device`` on-the-fly when explicit
++modifiers are not supported, because there's a risk of importing buffers
++with an implicit non-linear modifier as a linear buffer, resulting in
++misinterpreted buffer contents.
++
++Compositors should not send feedback parameters if they don't have a fallback
++path. For instance, compositors shouldn't send a format/modifier supported for
++direct scan-out but not supported by the rendering API for texturing.
++
++Compositors can decide to use multiple tranches to describe the allocation
++parameters optimized for texturing. For example, if there are formats which
++have a fast texturing path and formats which have a slower texturing path, the
++compositor can decide to expose two separate tranches.
++
++Compositors can decide to use intermediate tranches to describe code-paths
++slower than direct scan-out but faster than texturing. For instance, a
++compositor could insert an intermediate tranche if it's possible to use a
++mem2mem device to convert buffers to be able to use scan-out.
++
++``dev_t`` encoding
++==================
++
++The protocol carries ``dev_t`` values on the wire using arrays. A compositor
++written in C can encode the values as follows:
++
++.. code-block:: c
++
++    struct stat drm_node_stat;
++    struct wl_array dev_array = {
++        .size = sizeof(drm_node_stat.st_rdev),
++        .data = &drm_node_stat.st_rdev,
++    };
++
++A client can decode the values as follows:
++
++.. code-block:: c
++
++    dev_t dev;
++    assert(dev_array->size == sizeof(dev));
++    memcpy(&dev, dev_array->data, sizeof(dev));
++
++Because two DRM nodes can refer to the same DRM device while having different
++``dev_t`` values, clients should use ``drmDevicesEqual`` to compare two
++devices.
++
++``format_table`` encoding
++=========================
++
++The ``format_table`` event carries a file descriptor containing a list of
++format + modifier pairs. The list is an array of pairs which can be accessed
++with this C structure definition:
++
++.. code-block:: c
++
++    struct dmabuf_format_modifier {
++        uint32_t format;
++        uint32_t pad; /* unused */
++        uint64_t modifier;
++    };
++
++Integration with other APIs
++===========================
++
++- libdrm: ``drmGetDeviceFromDevId`` returns a ``drmDevice`` from a device ID.
++- EGL: the `EGL_EXT_device_drm_render_node`_ extension may be used to query the
++  DRM device render node used by a given EGL display. When unavailable, the
++  older `EGL_EXT_device_drm`_ extension may be used as a fallback.
++- Vulkan: the `VK_EXT_physical_device_drm`_ extension may be used to query the
++  DRM device used by a given ``VkPhysicalDevice``.
++
++.. _EGL_EXT_device_drm: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_device_drm.txt
++.. _EGL_EXT_device_drm_render_node: https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_device_drm_render_node.txt
++.. _VK_EXT_physical_device_drm: https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/VK_EXT_physical_device_drm.html
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..018f8761322aa5e55258f93c2d4f7b2cefaeadb4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,586 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="linux_dmabuf_unstable_v1">
++
++  <copyright>
++    Copyright © 2014, 2015 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_linux_dmabuf_v1" version="4">
++    <description summary="factory for creating dmabuf-based wl_buffers">
++      Following the interfaces from:
++      https://www.khronos.org/registry/egl/extensions/EXT/EGL_EXT_image_dma_buf_import.txt
++      https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_image_dma_buf_import_modifiers.txt
++      and the Linux DRM sub-system's AddFb2 ioctl.
++
++      This interface offers ways to create generic dmabuf-based wl_buffers.
++
++      Clients can use the get_surface_feedback request to get dmabuf feedback
++      for a particular surface. If the client wants to retrieve feedback not
++      tied to a surface, they can use the get_default_feedback request.
++
++      The following are required from clients:
++
++      - Clients must ensure that either all data in the dma-buf is
++        coherent for all subsequent read access or that coherency is
++        correctly handled by the underlying kernel-side dma-buf
++        implementation.
++
++      - Don't make any more attachments after sending the buffer to the
++        compositor. Making more attachments later increases the risk of
++        the compositor not being able to use (re-import) an existing
++        dmabuf-based wl_buffer.
++
++      The underlying graphics stack must ensure the following:
++
++      - The dmabuf file descriptors relayed to the server will stay valid
++        for the whole lifetime of the wl_buffer. This means the server may
++        at any time use those fds to import the dmabuf into any kernel
++        sub-system that might accept it.
++
++      However, when the underlying graphics stack fails to deliver the
++      promise, because of e.g. a device hot-unplug which raises internal
++      errors, after the wl_buffer has been successfully created the
++      compositor must not raise protocol errors to the client when dmabuf
++      import later fails.
++
++      To create a wl_buffer from one or more dmabufs, a client creates a
++      zwp_linux_dmabuf_params_v1 object with a zwp_linux_dmabuf_v1.create_params
++      request. All planes required by the intended format are added with
++      the 'add' request. Finally, a 'create' or 'create_immed' request is
++      issued, which has the following outcome depending on the import success.
++
++      The 'create' request,
++      - on success, triggers a 'created' event which provides the final
++        wl_buffer to the client.
++      - on failure, triggers a 'failed' event to convey that the server
++        cannot use the dmabufs received from the client.
++
++      For the 'create_immed' request,
++      - on success, the server immediately imports the added dmabufs to
++        create a wl_buffer. No event is sent from the server in this case.
++      - on failure, the server can choose to either:
++        - terminate the client by raising a fatal error.
++        - mark the wl_buffer as failed, and send a 'failed' event to the
++          client. If the client uses a failed wl_buffer as an argument to any
++          request, the behaviour is compositor implementation-defined.
++
++      For all DRM formats and unless specified in another protocol extension,
++      pre-multiplied alpha is used for pixel values.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unbind the factory">
++        Objects created through this interface, especially wl_buffers, will
++        remain valid.
++      </description>
++    </request>
++
++    <request name="create_params">
++      <description summary="create a temporary object for buffer parameters">
++        This temporary object is used to collect multiple dmabuf handles into
++        a single batch to create a wl_buffer. It can only be used once and
++        should be destroyed after a 'created' or 'failed' event has been
++        received.
++      </description>
++      <arg name="params_id" type="new_id" interface="zwp_linux_buffer_params_v1"
++           summary="the new temporary"/>
++    </request>
++
++    <event name="format">
++      <description summary="supported buffer format">
++        This event advertises one buffer format that the server supports.
++        All the supported formats are advertised once when the client
++        binds to this interface. A roundtrip after binding guarantees
++        that the client has received all supported formats.
++
++        For the definition of the format codes, see the
++        zwp_linux_buffer_params_v1::create request.
++
++        Starting version 4, the format event is deprecated and must not be
++        sent by compositors. Instead, use get_default_feedback or
++        get_surface_feedback.
++      </description>
++      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++    </event>
++
++    <event name="modifier" since="3">
++      <description summary="supported buffer format modifier">
++        This event advertises the formats that the server supports, along with
++        the modifiers supported for each format. All the supported modifiers
++        for all the supported formats are advertised once when the client
++        binds to this interface. A roundtrip after binding guarantees that
++        the client has received all supported format-modifier pairs.
++
++        For legacy support, DRM_FORMAT_MOD_INVALID (that is, modifier_hi ==
++        0x00ffffff and modifier_lo == 0xffffffff) is allowed in this event.
++        It indicates that the server can support the format with an implicit
++        modifier. When a plane has DRM_FORMAT_MOD_INVALID as its modifier, it
++        is as if no explicit modifier is specified. The effective modifier
++        will be derived from the dmabuf.
++
++        A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
++        a given format supports both explicit modifiers and implicit modifiers.
++
++        For the definition of the format and modifier codes, see the
++        zwp_linux_buffer_params_v1::create and zwp_linux_buffer_params_v1::add
++        requests.
++
++        Starting version 4, the modifier event is deprecated and must not be
++        sent by compositors. Instead, use get_default_feedback or
++        get_surface_feedback.
++      </description>
++      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++      <arg name="modifier_hi" type="uint"
++           summary="high 32 bits of layout modifier"/>
++      <arg name="modifier_lo" type="uint"
++           summary="low 32 bits of layout modifier"/>
++    </event>
++
++    <!-- Version 4 additions -->
++
++    <request name="get_default_feedback" since="4">
++      <description summary="get default feedback">
++        This request creates a new wp_linux_dmabuf_feedback object not bound
++        to a particular surface. This object will deliver feedback about dmabuf
++        parameters to use if the client doesn't support per-surface feedback
++        (see get_surface_feedback).
++      </description>
++      <arg name="id" type="new_id" interface="zwp_linux_dmabuf_feedback_v1"/>
++    </request>
++
++    <request name="get_surface_feedback" since="4">
++      <description summary="get feedback for a surface">
++        This request creates a new wp_linux_dmabuf_feedback object for the
++        specified wl_surface. This object will deliver feedback about dmabuf
++        parameters to use for buffers attached to this surface.
++
++        If the surface is destroyed before the wp_linux_dmabuf_feedback object,
++        the feedback object becomes inert.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_linux_dmabuf_feedback_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_linux_buffer_params_v1" version="4">
++    <description summary="parameters for creating a dmabuf-based wl_buffer">
++      This temporary object is a collection of dmabufs and other
++      parameters that together form a single logical buffer. The temporary
++      object may eventually create one wl_buffer unless cancelled by
++      destroying it before requesting 'create'.
++
++      Single-planar formats only require one dmabuf, however
++      multi-planar formats may require more than one dmabuf. For all
++      formats, an 'add' request must be called once per plane (even if the
++      underlying dmabuf fd is identical).
++
++      You must use consecutive plane indices ('plane_idx' argument for 'add')
++      from zero to the number of planes used by the drm_fourcc format code.
++      All planes required by the format must be given exactly once, but can
++      be given in any order. Each plane index can be set only once.
++    </description>
++
++    <enum name="error">
++      <entry name="already_used" value="0"
++             summary="the dmabuf_batch object has already been used to create a wl_buffer"/>
++      <entry name="plane_idx" value="1"
++             summary="plane index out of bounds"/>
++      <entry name="plane_set" value="2"
++             summary="the plane index was already set"/>
++      <entry name="incomplete" value="3"
++             summary="missing or too many planes to create a buffer"/>
++      <entry name="invalid_format" value="4"
++             summary="format not supported"/>
++      <entry name="invalid_dimensions" value="5"
++             summary="invalid width or height"/>
++      <entry name="out_of_bounds" value="6"
++             summary="offset + stride * height goes out of dmabuf bounds"/>
++      <entry name="invalid_wl_buffer" value="7"
++             summary="invalid wl_buffer resulted from importing dmabufs via
++               the create_immed request on given buffer_params"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="delete this object, used or not">
++        Cleans up the temporary data sent to the server for dmabuf-based
++        wl_buffer creation.
++      </description>
++    </request>
++
++    <request name="add">
++      <description summary="add a dmabuf to the temporary set">
++        This request adds one dmabuf to the set in this
++        zwp_linux_buffer_params_v1.
++
++        The 64-bit unsigned value combined from modifier_hi and modifier_lo
++        is the dmabuf layout modifier. DRM AddFB2 ioctl calls this the
++        fb modifier, which is defined in drm_mode.h of Linux UAPI.
++        This is an opaque token. Drivers use this token to express tiling,
++        compression, etc. driver-specific modifications to the base format
++        defined by the DRM fourcc code.
++
++        Starting from version 4, the invalid_format protocol error is sent if
++        the format + modifier pair was not advertised as supported.
++
++        This request raises the PLANE_IDX error if plane_idx is too large.
++        The error PLANE_SET is raised if attempting to set a plane that
++        was already set.
++      </description>
++      <arg name="fd" type="fd" summary="dmabuf fd"/>
++      <arg name="plane_idx" type="uint" summary="plane index"/>
++      <arg name="offset" type="uint" summary="offset in bytes"/>
++      <arg name="stride" type="uint" summary="stride in bytes"/>
++      <arg name="modifier_hi" type="uint"
++           summary="high 32 bits of layout modifier"/>
++      <arg name="modifier_lo" type="uint"
++           summary="low 32 bits of layout modifier"/>
++    </request>
++
++    <enum name="flags" bitfield="true">
++      <entry name="y_invert" value="1" summary="contents are y-inverted"/>
++      <entry name="interlaced" value="2" summary="content is interlaced"/>
++      <entry name="bottom_first" value="4" summary="bottom field first"/>
++    </enum>
++
++    <request name="create">
++      <description summary="create a wl_buffer from the given dmabufs">
++        This asks for creation of a wl_buffer from the added dmabuf
++        buffers. The wl_buffer is not created immediately but returned via
++        the 'created' event if the dmabuf sharing succeeds. The sharing
++        may fail at runtime for reasons a client cannot predict, in
++        which case the 'failed' event is triggered.
++
++        The 'format' argument is a DRM_FORMAT code, as defined by the
++        libdrm's drm_fourcc.h. The Linux kernel's DRM sub-system is the
++        authoritative source on how the format codes should work.
++
++        The 'flags' is a bitfield of the flags defined in enum "flags".
++        'y_invert' means the that the image needs to be y-flipped.
++
++        Flag 'interlaced' means that the frame in the buffer is not
++        progressive as usual, but interlaced. An interlaced buffer as
++        supported here must always contain both top and bottom fields.
++        The top field always begins on the first pixel row. The temporal
++        ordering between the two fields is top field first, unless
++        'bottom_first' is specified. It is undefined whether 'bottom_first'
++        is ignored if 'interlaced' is not set.
++
++        This protocol does not convey any information about field rate,
++        duration, or timing, other than the relative ordering between the
++        two fields in one buffer. A compositor may have to estimate the
++        intended field rate from the incoming buffer rate. It is undefined
++        whether the time of receiving wl_surface.commit with a new buffer
++        attached, applying the wl_surface state, wl_surface.frame callback
++        trigger, presentation, or any other point in the compositor cycle
++        is used to measure the frame or field times. There is no support
++        for detecting missed or late frames/fields/buffers either, and
++        there is no support whatsoever for cooperating with interlaced
++        compositor output.
++
++        The composited image quality resulting from the use of interlaced
++        buffers is explicitly undefined. A compositor may use elaborate
++        hardware features or software to deinterlace and create progressive
++        output frames from a sequence of interlaced input buffers, or it
++        may produce substandard image quality. However, compositors that
++        cannot guarantee reasonable image quality in all cases are recommended
++        to just reject all interlaced buffers.
++
++        Any argument errors, including non-positive width or height,
++        mismatch between the number of planes and the format, bad
++        format, bad offset or stride, may be indicated by fatal protocol
++        errors: INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS,
++        OUT_OF_BOUNDS.
++
++        Dmabuf import errors in the server that are not obvious client
++        bugs are returned via the 'failed' event as non-fatal. This
++        allows attempting dmabuf sharing and falling back in the client
++        if it fails.
++
++        This request can be sent only once in the object's lifetime, after
++        which the only legal request is destroy. This object should be
++        destroyed after issuing a 'create' request. Attempting to use this
++        object after issuing 'create' raises ALREADY_USED protocol error.
++
++        It is not mandatory to issue 'create'. If a client wants to
++        cancel the buffer creation, it can just destroy this object.
++      </description>
++      <arg name="width" type="int" summary="base plane width in pixels"/>
++      <arg name="height" type="int" summary="base plane height in pixels"/>
++      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++      <arg name="flags" type="uint" enum="flags" summary="see enum flags"/>
++    </request>
++
++    <event name="created">
++      <description summary="buffer creation succeeded">
++        This event indicates that the attempted buffer creation was
++        successful. It provides the new wl_buffer referencing the dmabuf(s).
++
++        Upon receiving this event, the client should destroy the
++        zlinux_dmabuf_params object.
++      </description>
++      <arg name="buffer" type="new_id" interface="wl_buffer"
++           summary="the newly created wl_buffer"/>
++    </event>
++
++    <event name="failed">
++      <description summary="buffer creation failed">
++        This event indicates that the attempted buffer creation has
++        failed. It usually means that one of the dmabuf constraints
++        has not been fulfilled.
++
++        Upon receiving this event, the client should destroy the
++        zlinux_buffer_params object.
++      </description>
++    </event>
++
++    <request name="create_immed" since="2">
++      <description summary="immediately create a wl_buffer from the given
++                     dmabufs">
++        This asks for immediate creation of a wl_buffer by importing the
++        added dmabufs.
++
++        In case of import success, no event is sent from the server, and the
++        wl_buffer is ready to be used by the client.
++
++        Upon import failure, either of the following may happen, as seen fit
++        by the implementation:
++        - the client is terminated with one of the following fatal protocol
++          errors:
++          - INCOMPLETE, INVALID_FORMAT, INVALID_DIMENSIONS, OUT_OF_BOUNDS,
++            in case of argument errors such as mismatch between the number
++            of planes and the format, bad format, non-positive width or
++            height, or bad offset or stride.
++          - INVALID_WL_BUFFER, in case the cause for failure is unknown or
++            plaform specific.
++        - the server creates an invalid wl_buffer, marks it as failed and
++          sends a 'failed' event to the client. The result of using this
++          invalid wl_buffer as an argument in any request by the client is
++          defined by the compositor implementation.
++
++        This takes the same arguments as a 'create' request, and obeys the
++        same restrictions.
++      </description>
++      <arg name="buffer_id" type="new_id" interface="wl_buffer"
++           summary="id for the newly created wl_buffer"/>
++      <arg name="width" type="int" summary="base plane width in pixels"/>
++      <arg name="height" type="int" summary="base plane height in pixels"/>
++      <arg name="format" type="uint" summary="DRM_FORMAT code"/>
++      <arg name="flags" type="uint" enum="flags" summary="see enum flags"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_linux_dmabuf_feedback_v1" version="4">
++    <description summary="dmabuf feedback">
++      This object advertises dmabuf parameters feedback. This includes the
++      preferred devices and the supported formats/modifiers.
++
++      The parameters are sent once when this object is created and whenever they
++      change. The done event is always sent once after all parameters have been
++      sent. When a single parameter changes, all parameters are re-sent by the
++      compositor.
++
++      Compositors can re-send the parameters when the current client buffer
++      allocations are sub-optimal. Compositors should not re-send the
++      parameters if re-allocating the buffers would not result in a more optimal
++      configuration. In particular, compositors should avoid sending the exact
++      same parameters multiple times in a row.
++
++      The tranche_target_device and tranche_modifier events are grouped by
++      tranches of preference. For each tranche, a tranche_target_device, one
++      tranche_flags and one or more tranche_modifier events are sent, followed
++      by a tranche_done event finishing the list. The tranches are sent in
++      descending order of preference. All formats and modifiers in the same
++      tranche have the same preference.
++
++      To send parameters, the compositor sends one main_device event, tranches
++      (each consisting of one tranche_target_device event, one tranche_flags
++      event, tranche_modifier events and then a tranche_done event), then one
++      done event.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the feedback object">
++        Using this request a client can tell the server that it is not going to
++        use the wp_linux_dmabuf_feedback object anymore.
++      </description>
++    </request>
++
++    <event name="done">
++      <description summary="all feedback has been sent">
++        This event is sent after all parameters of a wp_linux_dmabuf_feedback
++        object have been sent.
++
++        This allows changes to the wp_linux_dmabuf_feedback parameters to be
++        seen as atomic, even if they happen via multiple events.
++      </description>
++    </event>
++
++    <event name="format_table">
++      <description summary="format and modifier table">
++        This event provides a file descriptor which can be memory-mapped to
++        access the format and modifier table.
++
++        The table contains a tightly packed array of consecutive format +
++        modifier pairs. Each pair is 16 bytes wide. It contains a format as a
++        32-bit unsigned integer, followed by 4 bytes of unused padding, and a
++        modifier as a 64-bit unsigned integer. The native endianness is used.
++
++        The client must map the file descriptor in read-only private mode.
++
++        Compositors are not allowed to mutate the table file contents once this
++        event has been sent. Instead, compositors must create a new, separate
++        table file and re-send feedback parameters. Compositors are allowed to
++        store duplicate format + modifier pairs in the table.
++      </description>
++      <arg name="fd" type="fd" summary="table file descriptor"/>
++      <arg name="size" type="uint" summary="table size, in bytes"/>
++    </event>
++
++    <event name="main_device">
++      <description summary="preferred main device">
++        This event advertises the main device that the server prefers to use
++        when direct scan-out to the target device isn't possible. The
++        advertised main device may be different for each
++        wp_linux_dmabuf_feedback object, and may change over time.
++
++        There is exactly one main device. The compositor must send at least
++        one preference tranche with tranche_target_device equal to main_device.
++
++        Clients need to create buffers that the main device can import and
++        read from, otherwise creating the dmabuf wl_buffer will fail (see the
++        wp_linux_buffer_params.create and create_immed requests for details).
++        The main device will also likely be kept active by the compositor,
++        so clients can use it instead of waking up another device for power
++        savings.
++
++        In general the device is a DRM node. The DRM node type (primary vs.
++        render) is unspecified. Clients must not rely on the compositor sending
++        a particular node type. Clients cannot check two devices for equality
++        by comparing the dev_t value.
++
++        If explicit modifiers are not supported and the client performs buffer
++        allocations on a different device than the main device, then the client
++        must force the buffer to have a linear layout.
++      </description>
++      <arg name="device" type="array" summary="device dev_t value"/>
++    </event>
++
++    <event name="tranche_done">
++      <description summary="a preference tranche has been sent">
++        This event splits tranche_target_device and tranche_modifier events in
++        preference tranches. It is sent after a set of tranche_target_device
++        and tranche_modifier events; it represents the end of a tranche. The
++        next tranche will have a lower preference.
++      </description>
++    </event>
++
++    <event name="tranche_target_device">
++      <description summary="target device">
++        This event advertises the target device that the server prefers to use
++        for a buffer created given this tranche. The advertised target device
++        may be different for each preference tranche, and may change over time.
++
++        There is exactly one target device per tranche.
++
++        The target device may be a scan-out device, for example if the
++        compositor prefers to directly scan-out a buffer created given this
++        tranche. The target device may be a rendering device, for example if
++        the compositor prefers to texture from said buffer.
++
++        The client can use this hint to allocate the buffer in a way that makes
++        it accessible from the target device, ideally directly. The buffer must
++        still be accessible from the main device, either through direct import
++        or through a potentially more expensive fallback path. If the buffer
++        can't be directly imported from the main device then clients must be
++        prepared for the compositor changing the tranche priority or making
++        wl_buffer creation fail (see the wp_linux_buffer_params.create and
++        create_immed requests for details).
++
++        If the device is a DRM node, the DRM node type (primary vs. render) is
++        unspecified. Clients must not rely on the compositor sending a
++        particular node type. Clients cannot check two devices for equality by
++        comparing the dev_t value.
++
++        This event is tied to a preference tranche, see the tranche_done event.
++      </description>
++      <arg name="device" type="array" summary="device dev_t value"/>
++    </event>
++
++    <event name="tranche_formats">
++      <description summary="supported buffer format modifier">
++        This event advertises the format + modifier combinations that the
++        compositor supports.
++
++        It carries an array of indices, each referring to a format + modifier
++        pair in the last received format table (see the format_table event).
++        Each index is a 16-bit unsigned integer in native endianness.
++
++        For legacy support, DRM_FORMAT_MOD_INVALID is an allowed modifier.
++        It indicates that the server can support the format with an implicit
++        modifier. When a buffer has DRM_FORMAT_MOD_INVALID as its modifier, it
++        is as if no explicit modifier is specified. The effective modifier
++        will be derived from the dmabuf.
++
++        A compositor that sends valid modifiers and DRM_FORMAT_MOD_INVALID for
++        a given format supports both explicit modifiers and implicit modifiers.
++
++        Compositors must not send duplicate format + modifier pairs within the
++        same tranche or across two different tranches with the same target
++        device and flags.
++
++        This event is tied to a preference tranche, see the tranche_done event.
++
++        For the definition of the format and modifier codes, see the
++        wp_linux_buffer_params.create request.
++      </description>
++      <arg name="indices" type="array" summary="array of 16-bit indexes"/>
++    </event>
++
++    <enum name="tranche_flags" bitfield="true">
++      <entry name="scanout" value="1" summary="direct scan-out tranche"/>
++    </enum>
++
++    <event name="tranche_flags">
++      <description summary="tranche flags">
++        This event sets tranche-specific flags.
++
++        The scanout flag is a hint that direct scan-out may be attempted by the
++        compositor on the target device if the client appropriately allocates a
++        buffer. How to allocate a buffer that can be scanned out on the target
++        device is implementation-defined.
++
++        This event is tied to a preference tranche, see the tranche_done event.
++      </description>
++      <arg name="flags" type="uint" enum="tranche_flags" summary="tranche flags"/>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..59bcb6f05b014d9541f5cff609b45230d0685e28
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++Linux explicit synchronization (dma-fence) protocol
++
++Maintainers:
++Daniel Stone <daniels@collabora.com>
++Alexandros Frantzis <alexandros.frantzis@collabora.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ac9164183f6cf6536a3ad06b766c2b47c9c629f4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,256 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="zwp_linux_explicit_synchronization_unstable_v1">
++
++  <copyright>
++    Copyright 2016 The Chromium Authors.
++    Copyright 2017 Intel Corporation
++    Copyright 2018 Collabora, Ltd
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_linux_explicit_synchronization_v1" version="2">
++    <description summary="protocol for providing explicit synchronization">
++      This global is a factory interface, allowing clients to request
++      explicit synchronization for buffers on a per-surface basis.
++
++      See zwp_linux_surface_synchronization_v1 for more information.
++
++      This interface is derived from Chromium's
++      zcr_linux_explicit_synchronization_v1.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy explicit synchronization factory object">
++        Destroy this explicit synchronization factory object. Other objects,
++        including zwp_linux_surface_synchronization_v1 objects created by this
++        factory, shall not be affected by this request.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="synchronization_exists" value="0"
++             summary="the surface already has a synchronization object associated"/>
++    </enum>
++
++    <request name="get_synchronization">
++      <description summary="extend surface interface for explicit synchronization">
++        Instantiate an interface extension for the given wl_surface to provide
++        explicit synchronization.
++
++        If the given wl_surface already has an explicit synchronization object
++        associated, the synchronization_exists protocol error is raised.
++
++        Graphics APIs, like EGL or Vulkan, that manage the buffer queue and
++        commits of a wl_surface themselves, are likely to be using this
++        extension internally. If a client is using such an API for a
++        wl_surface, it should not directly use this extension on that surface,
++        to avoid raising a synchronization_exists protocol error.
++      </description>
++
++      <arg name="id" type="new_id"
++           interface="zwp_linux_surface_synchronization_v1"
++           summary="the new synchronization interface id"/>
++      <arg name="surface" type="object" interface="wl_surface"
++           summary="the surface"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_linux_surface_synchronization_v1" version="2">
++    <description summary="per-surface explicit synchronization support">
++      This object implements per-surface explicit synchronization.
++
++      Synchronization refers to co-ordination of pipelined operations performed
++      on buffers. Most GPU clients will schedule an asynchronous operation to
++      render to the buffer, then immediately send the buffer to the compositor
++      to be attached to a surface.
++
++      In implicit synchronization, ensuring that the rendering operation is
++      complete before the compositor displays the buffer is an implementation
++      detail handled by either the kernel or userspace graphics driver.
++
++      By contrast, in explicit synchronization, dma_fence objects mark when the
++      asynchronous operations are complete. When submitting a buffer, the
++      client provides an acquire fence which will be waited on before the
++      compositor accesses the buffer. The Wayland server, through a
++      zwp_linux_buffer_release_v1 object, will inform the client with an event
++      which may be accompanied by a release fence, when the compositor will no
++      longer access the buffer contents due to the specific commit that
++      requested the release event.
++
++      Each surface can be associated with only one object of this interface at
++      any time.
++
++      In version 1 of this interface, explicit synchronization is only
++      guaranteed to be supported for buffers created with any version of the
++      wp_linux_dmabuf buffer factory. Version 2 additionally guarantees
++      explicit synchronization support for opaque EGL buffers, which is a type
++      of platform specific buffers described in the EGL_WL_bind_wayland_display
++      extension. Compositors are free to support explicit synchronization for
++      additional buffer types.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy synchronization object">
++        Destroy this explicit synchronization object.
++
++        Any fence set by this object with set_acquire_fence since the last
++        commit will be discarded by the server. Any fences set by this object
++        before the last commit are not affected.
++
++        zwp_linux_buffer_release_v1 objects created by this object are not
++        affected by this request.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="invalid_fence" value="0"
++             summary="the fence specified by the client could not be imported"/>
++      <entry name="duplicate_fence" value="1"
++             summary="multiple fences added for a single surface commit"/>
++      <entry name="duplicate_release" value="2"
++             summary="multiple releases added for a single surface commit"/>
++      <entry name="no_surface" value="3"
++             summary="the associated wl_surface was destroyed"/>
++      <entry name="unsupported_buffer" value="4"
++             summary="the buffer does not support explicit synchronization"/>
++      <entry name="no_buffer" value="5"
++             summary="no buffer was attached"/>
++    </enum>
++
++    <request name="set_acquire_fence">
++      <description summary="set the acquire fence">
++        Set the acquire fence that must be signaled before the compositor
++        may sample from the buffer attached with wl_surface.attach. The fence
++        is a dma_fence kernel object.
++
++        The acquire fence is double-buffered state, and will be applied on the
++        next wl_surface.commit request for the associated surface. Thus, it
++        applies only to the buffer that is attached to the surface at commit
++        time.
++
++        If the provided fd is not a valid dma_fence fd, then an INVALID_FENCE
++        error is raised.
++
++        If a fence has already been attached during the same commit cycle, a
++        DUPLICATE_FENCE error is raised.
++
++        If the associated wl_surface was destroyed, a NO_SURFACE error is
++        raised.
++
++        If at surface commit time the attached buffer does not support explicit
++        synchronization, an UNSUPPORTED_BUFFER error is raised.
++
++        If at surface commit time there is no buffer attached, a NO_BUFFER
++        error is raised.
++      </description>
++      <arg name="fd" type="fd" summary="acquire fence fd"/>
++    </request>
++
++    <request name="get_release">
++      <description summary="release fence for last-attached buffer">
++        Create a listener for the release of the buffer attached by the
++        client with wl_surface.attach. See zwp_linux_buffer_release_v1
++        documentation for more information.
++
++        The release object is double-buffered state, and will be associated
++        with the buffer that is attached to the surface at wl_surface.commit
++        time.
++
++        If a zwp_linux_buffer_release_v1 object has already been requested for
++        the surface in the same commit cycle, a DUPLICATE_RELEASE error is
++        raised.
++
++        If the associated wl_surface was destroyed, a NO_SURFACE error
++        is raised.
++
++        If at surface commit time there is no buffer attached, a NO_BUFFER
++        error is raised.
++      </description>
++      <arg name="release" type="new_id" interface="zwp_linux_buffer_release_v1"
++           summary="new zwp_linux_buffer_release_v1 object"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_linux_buffer_release_v1" version="1">
++    <description summary="buffer release explicit synchronization">
++      This object is instantiated in response to a
++      zwp_linux_surface_synchronization_v1.get_release request.
++
++      It provides an alternative to wl_buffer.release events, providing a
++      unique release from a single wl_surface.commit request. The release event
++      also supports explicit synchronization, providing a fence FD for the
++      client to synchronize against.
++
++      Exactly one event, either a fenced_release or an immediate_release, will
++      be emitted for the wl_surface.commit request. The compositor can choose
++      release by release which event it uses.
++
++      This event does not replace wl_buffer.release events; servers are still
++      required to send those events.
++
++      Once a buffer release object has delivered a 'fenced_release' or an
++      'immediate_release' event it is automatically destroyed.
++    </description>
++
++    <event name="fenced_release" type="destructor">
++      <description summary="release buffer with fence">
++        Sent when the compositor has finalised its usage of the associated
++        buffer for the relevant commit, providing a dma_fence which will be
++        signaled when all operations by the compositor on that buffer for that
++        commit have finished.
++
++        Once the fence has signaled, and assuming the associated buffer is not
++        pending release from other wl_surface.commit requests, no additional
++        explicit or implicit synchronization is required to safely reuse or
++        destroy the buffer.
++
++        This event destroys the zwp_linux_buffer_release_v1 object.
++      </description>
++      <arg name="fence" type="fd" summary="fence for last operation on buffer"/>
++    </event>
++
++    <event name="immediate_release" type="destructor">
++      <description summary="release buffer immediately">
++        Sent when the compositor has finalised its usage of the associated
++        buffer for the relevant commit, and either performed no operations
++        using it, or has a guarantee that all its operations on that buffer for
++        that commit have finished.
++
++        Once this event is received, and assuming the associated buffer is not
++        pending release from other wl_surface.commit requests, no additional
++        explicit or implicit synchronization is required to safely reuse or
++        destroy the buffer.
++
++        This event destroys the zwp_linux_buffer_release_v1 object.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8a242f8d7e5f335583c55de5c29951e03025a3d4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Pointer constraints protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..efd64b6603c8da85bbdfccef737e07da133d1d33
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,339 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="pointer_constraints_unstable_v1">
++
++  <copyright>
++    Copyright © 2014      Jonas Ådahl
++    Copyright © 2015      Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="protocol for constraining pointer motions">
++    This protocol specifies a set of interfaces used for adding constraints to
++    the motion of a pointer. Possible constraints include confining pointer
++    motions to a given region, or locking it to its current position.
++
++    In order to constrain the pointer, a client must first bind the global
++    interface "wp_pointer_constraints" which, if a compositor supports pointer
++    constraints, is exposed by the registry. Using the bound global object, the
++    client uses the request that corresponds to the type of constraint it wants
++    to make. See wp_pointer_constraints for more details.
++
++    Warning! The protocol described in this file is experimental and backward
++    incompatible changes may be made. Backward compatible changes may be added
++    together with the corresponding interface version bump. Backward
++    incompatible changes are done by bumping the version number in the protocol
++    and interface names and resetting the interface version. Once the protocol
++    is to be declared stable, the 'z' prefix and the version number in the
++    protocol and interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zwp_pointer_constraints_v1" version="1">
++    <description summary="constrain the movement of a pointer">
++      The global interface exposing pointer constraining functionality. It
++      exposes two requests: lock_pointer for locking the pointer to its
++      position, and confine_pointer for locking the pointer to a region.
++
++      The lock_pointer and confine_pointer requests create the objects
++      wp_locked_pointer and wp_confined_pointer respectively, and the client can
++      use these objects to interact with the lock.
++
++      For any surface, only one lock or confinement may be active across all
++      wl_pointer objects of the same seat. If a lock or confinement is requested
++      when another lock or confinement is active or requested on the same surface
++      and with any of the wl_pointer objects of the same seat, an
++      'already_constrained' error will be raised.
++    </description>
++
++    <enum name="error">
++      <description summary="wp_pointer_constraints error values">
++      These errors can be emitted in response to wp_pointer_constraints
++      requests.
++      </description>
++      <entry name="already_constrained" value="1"
++           summary="pointer constraint already requested on that surface"/>
++    </enum>
++
++    <enum name="lifetime">
++      <description summary="constraint lifetime">
++      These values represent different lifetime semantics. They are passed
++      as arguments to the factory requests to specify how the constraint
++      lifetimes should be managed.
++      </description>
++      <entry name="oneshot" value="1">
++      <description summary="the pointer constraint is defunct once deactivated">
++        A oneshot pointer constraint will never reactivate once it has been
++        deactivated. See the corresponding deactivation event
++        (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
++        details.
++      </description>
++      </entry>
++      <entry name="persistent" value="2">
++      <description summary="the pointer constraint may reactivate">
++        A persistent pointer constraint may again reactivate once it has
++        been deactivated. See the corresponding deactivation event
++        (wp_locked_pointer.unlocked and wp_confined_pointer.unconfined) for
++        details.
++      </description>
++      </entry>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pointer constraints manager object">
++      Used by the client to notify the server that it will no longer use this
++      pointer constraints object.
++      </description>
++    </request>
++
++    <request name="lock_pointer">
++      <description summary="lock pointer to a position">
++      The lock_pointer request lets the client request to disable movements of
++      the virtual pointer (i.e. the cursor), effectively locking the pointer
++      to a position. This request may not take effect immediately; in the
++      future, when the compositor deems implementation-specific constraints
++      are satisfied, the pointer lock will be activated and the compositor
++      sends a locked event.
++
++      The protocol provides no guarantee that the constraints are ever
++      satisfied, and does not require the compositor to send an error if the
++      constraints cannot ever be satisfied. It is thus possible to request a
++      lock that will never activate.
++
++      There may not be another pointer constraint of any kind requested or
++      active on the surface for any of the wl_pointer objects of the seat of
++      the passed pointer when requesting a lock. If there is, an error will be
++      raised. See general pointer lock documentation for more details.
++
++      The intersection of the region passed with this request and the input
++      region of the surface is used to determine where the pointer must be
++      in order for the lock to activate. It is up to the compositor whether to
++      warp the pointer or require some kind of user interaction for the lock
++      to activate. If the region is null the surface input region is used.
++
++      A surface may receive pointer focus without the lock being activated.
++
++      The request creates a new object wp_locked_pointer which is used to
++      interact with the lock as well as receive updates about its state. See
++      the the description of wp_locked_pointer for further information.
++
++      Note that while a pointer is locked, the wl_pointer objects of the
++      corresponding seat will not emit any wl_pointer.motion events, but
++      relative motion events will still be emitted via wp_relative_pointer
++      objects of the same seat. wl_pointer.axis and wl_pointer.button events
++      are unaffected.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_locked_pointer_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="surface to lock pointer to"/>
++      <arg name="pointer" type="object" interface="wl_pointer"
++         summary="the pointer that should be locked"/>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="region of surface"/>
++      <arg name="lifetime" type="uint" enum="lifetime" summary="lock lifetime"/>
++    </request>
++
++    <request name="confine_pointer">
++      <description summary="confine pointer to a region">
++      The confine_pointer request lets the client request to confine the
++      pointer cursor to a given region. This request may not take effect
++      immediately; in the future, when the compositor deems implementation-
++      specific constraints are satisfied, the pointer confinement will be
++      activated and the compositor sends a confined event.
++
++      The intersection of the region passed with this request and the input
++      region of the surface is used to determine where the pointer must be
++      in order for the confinement to activate. It is up to the compositor
++      whether to warp the pointer or require some kind of user interaction for
++      the confinement to activate. If the region is null the surface input
++      region is used.
++
++      The request will create a new object wp_confined_pointer which is used
++      to interact with the confinement as well as receive updates about its
++      state. See the the description of wp_confined_pointer for further
++      information.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_confined_pointer_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="surface to lock pointer to"/>
++      <arg name="pointer" type="object" interface="wl_pointer"
++         summary="the pointer that should be confined"/>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="region of surface"/>
++      <arg name="lifetime" type="uint" enum="lifetime" summary="confinement lifetime"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_locked_pointer_v1" version="1">
++    <description summary="receive relative pointer motion events">
++      The wp_locked_pointer interface represents a locked pointer state.
++
++      While the lock of this object is active, the wl_pointer objects of the
++      associated seat will not emit any wl_pointer.motion events.
++
++      This object will send the event 'locked' when the lock is activated.
++      Whenever the lock is activated, it is guaranteed that the locked surface
++      will already have received pointer focus and that the pointer will be
++      within the region passed to the request creating this object.
++
++      To unlock the pointer, send the destroy request. This will also destroy
++      the wp_locked_pointer object.
++
++      If the compositor decides to unlock the pointer the unlocked event is
++      sent. See wp_locked_pointer.unlock for details.
++
++      When unlocking, the compositor may warp the cursor position to the set
++      cursor position hint. If it does, it will not result in any relative
++      motion events emitted via wp_relative_pointer.
++
++      If the surface the lock was requested on is destroyed and the lock is not
++      yet activated, the wp_locked_pointer object is now defunct and must be
++      destroyed.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the locked pointer object">
++      Destroy the locked pointer object. If applicable, the compositor will
++      unlock the pointer.
++      </description>
++    </request>
++
++    <request name="set_cursor_position_hint">
++      <description summary="set the pointer cursor position hint">
++      Set the cursor position hint relative to the top left corner of the
++      surface.
++
++      If the client is drawing its own cursor, it should update the position
++      hint to the position of its own cursor. A compositor may use this
++      information to warp the pointer upon unlock in order to avoid pointer
++      jumps.
++
++      The cursor position hint is double buffered. The new hint will only take
++      effect when the associated surface gets it pending state applied. See
++      wl_surface.commit for details.
++      </description>
++      <arg name="surface_x" type="fixed"
++         summary="surface-local x coordinate"/>
++      <arg name="surface_y" type="fixed"
++         summary="surface-local y coordinate"/>
++    </request>
++
++    <request name="set_region">
++      <description summary="set a new lock region">
++      Set a new region used to lock the pointer.
++
++      The new lock region is double-buffered. The new lock region will
++      only take effect when the associated surface gets its pending state
++      applied. See wl_surface.commit for details.
++
++      For details about the lock region, see wp_locked_pointer.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="region of surface"/>
++    </request>
++
++    <event name="locked">
++      <description summary="lock activation event">
++      Notification that the pointer lock of the seat's pointer is activated.
++      </description>
++    </event>
++
++    <event name="unlocked">
++      <description summary="lock deactivation event">
++      Notification that the pointer lock of the seat's pointer is no longer
++      active. If this is a oneshot pointer lock (see
++      wp_pointer_constraints.lifetime) this object is now defunct and should
++      be destroyed. If this is a persistent pointer lock (see
++      wp_pointer_constraints.lifetime) this pointer lock may again
++      reactivate in the future.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="zwp_confined_pointer_v1" version="1">
++    <description summary="confined pointer object">
++      The wp_confined_pointer interface represents a confined pointer state.
++
++      This object will send the event 'confined' when the confinement is
++      activated. Whenever the confinement is activated, it is guaranteed that
++      the surface the pointer is confined to will already have received pointer
++      focus and that the pointer will be within the region passed to the request
++      creating this object. It is up to the compositor to decide whether this
++      requires some user interaction and if the pointer will warp to within the
++      passed region if outside.
++
++      To unconfine the pointer, send the destroy request. This will also destroy
++      the wp_confined_pointer object.
++
++      If the compositor decides to unconfine the pointer the unconfined event is
++      sent. The wp_confined_pointer object is at this point defunct and should
++      be destroyed.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the confined pointer object">
++      Destroy the confined pointer object. If applicable, the compositor will
++      unconfine the pointer.
++      </description>
++    </request>
++
++    <request name="set_region">
++      <description summary="set a new confine region">
++      Set a new region used to confine the pointer.
++
++      The new confine region is double-buffered. The new confine region will
++      only take effect when the associated surface gets its pending state
++      applied. See wl_surface.commit for details.
++
++      If the confinement is active when the new confinement region is applied
++      and the pointer ends up outside of newly applied region, the pointer may
++      warped to a position within the new confinement region. If warped, a
++      wl_pointer.motion event will be emitted, but no
++      wp_relative_pointer.relative_motion event.
++
++      The compositor may also, instead of using the new region, unconfine the
++      pointer.
++
++      For details about the confine region, see wp_confined_pointer.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="region of surface"/>
++    </request>
++
++    <event name="confined">
++      <description summary="pointer confined">
++      Notification that the pointer confinement of the seat's pointer is
++      activated.
++      </description>
++    </event>
++
++    <event name="unconfined">
++      <description summary="pointer unconfined">
++      Notification that the pointer confinement of the seat's pointer is no
++      longer active. If this is a oneshot pointer confinement (see
++      wp_pointer_constraints.lifetime) this object is now defunct and should
++      be destroyed. If this is a persistent pointer confinement (see
++      wp_pointer_constraints.lifetime) this pointer confinement may again
++      reactivate in the future.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a419632b0f5079055c1642b137f6fa2e1e5e5362
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Pointer gestures protocol
++
++Maintainers:
++Carlos Garnacho <carlosg@gnome.org>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f92a1160594a44212e3582939ad665948d597f64
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,253 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="pointer_gestures_unstable_v1">
++
++  <interface name="zwp_pointer_gestures_v1" version="3">
++    <description summary="touchpad gestures">
++      A global interface to provide semantic touchpad gestures for a given
++      pointer.
++
++      Three gestures are currently supported: swipe, pinch, and hold.
++      Pinch and swipe gestures follow a three-stage cycle: begin, update,
++      end, hold gestures follow a two-stage cycle: begin and end. All
++      gestures are identified by a unique id.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="get_swipe_gesture">
++      <description summary="get swipe gesture">
++      Create a swipe gesture object. See the
++      wl_pointer_gesture_swipe interface for details.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_pointer_gesture_swipe_v1"/>
++      <arg name="pointer" type="object" interface="wl_pointer"/>
++    </request>
++
++    <request name="get_pinch_gesture">
++      <description summary="get pinch gesture">
++      Create a pinch gesture object. See the
++      wl_pointer_gesture_pinch interface for details.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_pointer_gesture_pinch_v1"/>
++      <arg name="pointer" type="object" interface="wl_pointer"/>
++    </request>
++
++    <!-- Version 2 additions -->
++
++    <request name="release" type="destructor" since="2">
++      <description summary="destroy the pointer gesture object">
++      Destroy the pointer gesture object. Swipe, pinch and hold objects
++      created via this gesture object remain valid.
++      </description>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <request name="get_hold_gesture" since="3">
++      <description summary="get hold gesture">
++      Create a hold gesture object. See the
++      wl_pointer_gesture_hold interface for details.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_pointer_gesture_hold_v1"/>
++      <arg name="pointer" type="object" interface="wl_pointer"/>
++    </request>
++
++  </interface>
++
++  <interface name="zwp_pointer_gesture_swipe_v1" version="2">
++    <description summary="a swipe gesture object">
++      A swipe gesture object notifies a client about a multi-finger swipe
++      gesture detected on an indirect input device such as a touchpad.
++      The gesture is usually initiated by multiple fingers moving in the
++      same direction but once initiated the direction may change.
++      The precise conditions of when such a gesture is detected are
++      implementation-dependent.
++
++      A gesture consists of three stages: begin, update (optional) and end.
++      There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++      same pointer/seat, how compositors prevent these situations is
++      implementation-dependent.
++
++      A gesture may be cancelled by the compositor or the hardware.
++      Clients should not consider performing permanent or irreversible
++      actions until the end of a gesture has been received.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pointer swipe gesture object"/>
++    </request>
++
++    <event name="begin">
++      <description summary="multi-finger swipe begin">
++      This event is sent when a multi-finger swipe gesture is detected
++      on the device.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="fingers" type="uint" summary="number of fingers"/>
++    </event>
++
++    <event name="update">
++      <description summary="multi-finger swipe motion">
++      This event is sent when a multi-finger swipe gesture changes the
++      position of the logical center.
++
++      The dx and dy coordinates are relative coordinates of the logical
++      center of the gesture compared to the previous event.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
++      <arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
++    </event>
++
++    <event name="end">
++      <description summary="multi-finger swipe end">
++      This event is sent when a multi-finger swipe gesture ceases to
++      be valid. This may happen when one or more fingers are lifted or
++      the gesture is cancelled.
++
++      When a gesture is cancelled, the client should undo state changes
++      caused by this gesture. What causes a gesture to be cancelled is
++      implementation-dependent.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_pointer_gesture_pinch_v1" version="2">
++    <description summary="a pinch gesture object">
++      A pinch gesture object notifies a client about a multi-finger pinch
++      gesture detected on an indirect input device such as a touchpad.
++      The gesture is usually initiated by multiple fingers moving towards
++      each other or away from each other, or by two or more fingers rotating
++      around a logical center of gravity. The precise conditions of when
++      such a gesture is detected are implementation-dependent.
++
++      A gesture consists of three stages: begin, update (optional) and end.
++      There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++      same pointer/seat, how compositors prevent these situations is
++      implementation-dependent.
++
++      A gesture may be cancelled by the compositor or the hardware.
++      Clients should not consider performing permanent or irreversible
++      actions until the end of a gesture has been received.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pinch gesture object"/>
++    </request>
++
++    <event name="begin">
++      <description summary="multi-finger pinch begin">
++      This event is sent when a multi-finger pinch gesture is detected
++      on the device.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="fingers" type="uint" summary="number of fingers"/>
++    </event>
++
++    <event name="update">
++      <description summary="multi-finger pinch motion">
++      This event is sent when a multi-finger pinch gesture changes the
++      position of the logical center, the rotation or the relative scale.
++
++      The dx and dy coordinates are relative coordinates in the
++      surface coordinate space of the logical center of the gesture.
++
++      The scale factor is an absolute scale compared to the
++      pointer_gesture_pinch.begin event, e.g. a scale of 2 means the fingers
++      are now twice as far apart as on pointer_gesture_pinch.begin.
++
++      The rotation is the relative angle in degrees clockwise compared to the previous
++      pointer_gesture_pinch.begin or pointer_gesture_pinch.update event.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="dx" type="fixed" summary="delta x coordinate in surface coordinate space"/>
++      <arg name="dy" type="fixed" summary="delta y coordinate in surface coordinate space"/>
++      <arg name="scale" type="fixed" summary="scale relative to the initial finger position"/>
++      <arg name="rotation" type="fixed" summary="angle in degrees cw relative to the previous event"/>
++    </event>
++
++    <event name="end">
++      <description summary="multi-finger pinch end">
++      This event is sent when a multi-finger pinch gesture ceases to
++      be valid. This may happen when one or more fingers are lifted or
++      the gesture is cancelled.
++
++      When a gesture is cancelled, the client should undo state changes
++      caused by this gesture. What causes a gesture to be cancelled is
++      implementation-dependent.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++    </event>
++
++  </interface>
++
++  <interface name="zwp_pointer_gesture_hold_v1" version="3">
++    <description summary="a hold gesture object">
++      A hold gesture object notifies a client about a single- or
++      multi-finger hold gesture detected on an indirect input device such as
++      a touchpad. The gesture is usually initiated by one or more fingers
++      being held down without significant movement. The precise conditions
++      of when such a gesture is detected are implementation-dependent.
++
++      In particular, this gesture may be used to cancel kinetic scrolling.
++
++      A hold gesture consists of two stages: begin and end. Unlike pinch and
++      swipe there is no update stage.
++      There cannot be multiple simultaneous hold, pinch or swipe gestures on a
++      same pointer/seat, how compositors prevent these situations is
++      implementation-dependent.
++
++      A gesture may be cancelled by the compositor or the hardware.
++      Clients should not consider performing permanent or irreversible
++      actions until the end of a gesture has been received.
++    </description>
++
++    <request name="destroy" type="destructor" since="3">
++      <description summary="destroy the hold gesture object"/>
++    </request>
++
++    <event name="begin" since="3">
++      <description summary="multi-finger hold begin">
++      This event is sent when a hold gesture is detected on the device.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="fingers" type="uint" summary="number of fingers"/>
++    </event>
++
++    <event name="end" since="3">
++      <description summary="multi-finger hold end">
++      This event is sent when a hold gesture ceases to
++      be valid. This may happen when the holding fingers are lifted or
++      the gesture is cancelled, for example if the fingers move past an
++      implementation-defined threshold, the finger count changes or the hold
++      gesture changes into a different type of gesture.
++
++      When a gesture is cancelled, the client may need to undo state changes
++      caused by this gesture. What causes a gesture to be cancelled is
++      implementation-dependent.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="cancelled" type="int" summary="1 if the gesture was cancelled, 0 otherwise"/>
++    </event>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ae0a4020cac48c7499d126d063b552f506e00e4d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Primary selection protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e5a39e34cec3dec8b30198fa00421871603bfb3e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,225 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wp_primary_selection_unstable_v1">
++  <copyright>
++    Copyright © 2015, 2016 Red Hat
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Primary selection protocol">
++    This protocol provides the ability to have a primary selection device to
++    match that of the X server. This primary selection is a shortcut to the
++    common clipboard selection, where text just needs to be selected in order
++    to allow copying it elsewhere. The de facto way to perform this action
++    is the middle mouse button, although it is not limited to this one.
++
++    Clients wishing to honor primary selection should create a primary
++    selection source and set it as the selection through
++    wp_primary_selection_device.set_selection whenever the text selection
++    changes. In order to minimize calls in pointer-driven text selection,
++    it should happen only once after the operation finished. Similarly,
++    a NULL source should be set when text is unselected.
++
++    wp_primary_selection_offer objects are first announced through the
++    wp_primary_selection_device.data_offer event. Immediately after this event,
++    the primary data offer will emit wp_primary_selection_offer.offer events
++    to let know of the mime types being offered.
++
++    When the primary selection changes, the client with the keyboard focus
++    will receive wp_primary_selection_device.selection events. Only the client
++    with the keyboard focus will receive such events with a non-NULL
++    wp_primary_selection_offer. Across keyboard focus changes, previously
++    focused clients will receive wp_primary_selection_device.events with a
++    NULL wp_primary_selection_offer.
++
++    In order to request the primary selection data, the client must pass
++    a recent serial pertaining to the press event that is triggering the
++    operation, if the compositor deems the serial valid and recent, the
++    wp_primary_selection_source.send event will happen in the other end
++    to let the transfer begin. The client owning the primary selection
++    should write the requested data, and close the file descriptor
++    immediately.
++
++    If the primary selection owner client disappeared during the transfer,
++    the client reading the data will receive a
++    wp_primary_selection_device.selection event with a NULL
++    wp_primary_selection_offer, the client should take this as a hint
++    to finish the reads related to the no longer existing offer.
++
++    The primary selection owner should be checking for errors during
++    writes, merely cancelling the ongoing transfer if any happened.
++  </description>
++
++  <interface name="zwp_primary_selection_device_manager_v1" version="1">
++    <description summary="X primary selection emulation">
++      The primary selection device manager is a singleton global object that
++      provides access to the primary selection. It allows to create
++      wp_primary_selection_source objects, as well as retrieving the per-seat
++      wp_primary_selection_device objects.
++    </description>
++
++    <request name="create_source">
++      <description summary="create a new primary selection source">
++        Create a new primary selection source.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_primary_selection_source_v1"/>
++    </request>
++
++    <request name="get_device">
++      <description summary="create a new primary selection device">
++        Create a new data device for a given seat.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_primary_selection_device_v1"/>
++      <arg name="seat" type="object" interface="wl_seat"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the primary selection device manager">
++        Destroy the primary selection device manager.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="zwp_primary_selection_device_v1" version="1">
++    <request name="set_selection">
++      <description summary="set the primary selection">
++        Replaces the current selection. The previous owner of the primary
++        selection will receive a wp_primary_selection_source.cancelled event.
++
++        To unset the selection, set the source to NULL.
++      </description>
++      <arg name="source" type="object" interface="zwp_primary_selection_source_v1" allow-null="true"/>
++      <arg name="serial" type="uint" summary="serial of the event that triggered this request"/>
++    </request>
++
++    <event name="data_offer">
++      <description summary="introduce a new wp_primary_selection_offer">
++        Introduces a new wp_primary_selection_offer object that may be used
++        to receive the current primary selection. Immediately following this
++        event, the new wp_primary_selection_offer object will send
++        wp_primary_selection_offer.offer events to describe the offered mime
++        types.
++      </description>
++      <arg name="offer" type="new_id" interface="zwp_primary_selection_offer_v1"/>
++    </event>
++
++    <event name="selection">
++      <description summary="advertise a new primary selection">
++        The wp_primary_selection_device.selection event is sent to notify the
++        client of a new primary selection. This event is sent after the
++        wp_primary_selection.data_offer event introducing this object, and after
++        the offer has announced its mimetypes through
++        wp_primary_selection_offer.offer.
++
++        The data_offer is valid until a new offer or NULL is received
++        or until the client loses keyboard focus. The client must destroy the
++        previous selection data_offer, if any, upon receiving this event.
++      </description>
++      <arg name="id" type="object" interface="zwp_primary_selection_offer_v1" allow-null="true"/>
++    </event>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the primary selection device">
++        Destroy the primary selection device.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="zwp_primary_selection_offer_v1" version="1">
++    <description summary="offer to transfer primary selection contents">
++      A wp_primary_selection_offer represents an offer to transfer the contents
++      of the primary selection clipboard to the client. Similar to
++      wl_data_offer, the offer also describes the mime types that the data can
++      be converted to and provides the mechanisms for transferring the data
++      directly to the client.
++    </description>
++
++    <request name="receive">
++      <description summary="request that the data is transferred">
++        To transfer the contents of the primary selection clipboard, the client
++        issues this request and indicates the mime type that it wants to
++        receive. The transfer happens through the passed file descriptor
++        (typically created with the pipe system call). The source client writes
++        the data in the mime type representation requested and then closes the
++        file descriptor.
++
++        The receiving client reads from the read end of the pipe until EOF and
++        closes its end, at which point the transfer is complete.
++      </description>
++      <arg name="mime_type" type="string"/>
++      <arg name="fd" type="fd"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the primary selection offer">
++        Destroy the primary selection offer.
++      </description>
++    </request>
++
++    <event name="offer">
++      <description summary="advertise offered mime type">
++        Sent immediately after creating announcing the
++        wp_primary_selection_offer through
++        wp_primary_selection_device.data_offer. One event is sent per offered
++        mime type.
++      </description>
++      <arg name="mime_type" type="string"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_primary_selection_source_v1" version="1">
++    <description summary="offer to replace the contents of the primary selection">
++      The source side of a wp_primary_selection_offer, it provides a way to
++      describe the offered data and respond to requests to transfer the
++      requested contents of the primary selection clipboard.
++    </description>
++
++    <request name="offer">
++      <description summary="add an offered mime type">
++        This request adds a mime type to the set of mime types advertised to
++        targets. Can be called several times to offer multiple types.
++      </description>
++      <arg name="mime_type" type="string"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the primary selection source">
++        Destroy the primary selection source.
++      </description>
++    </request>
++
++    <event name="send">
++      <description summary="send the primary selection contents">
++        Request for the current primary selection contents from the client.
++        Send the specified mime type over the passed file descriptor, then
++        close it.
++      </description>
++      <arg name="mime_type" type="string"/>
++      <arg name="fd" type="fd"/>
++    </event>
++
++    <event name="cancelled">
++      <description summary="request for primary selection contents was canceled">
++        This primary selection source is no longer valid. The client should
++        clean up and destroy this primary selection source.
++      </description>
++    </event>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..64c42a126e72f0701cc6cacecc7c1254b42d2d8d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Relative pointer protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ca6f81d12ac1de1960ae1417cf4179def59b69e9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,136 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="relative_pointer_unstable_v1">
++
++  <copyright>
++    Copyright © 2014      Jonas Ådahl
++    Copyright © 2015      Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="protocol for relative pointer motion events">
++    This protocol specifies a set of interfaces used for making clients able to
++    receive relative pointer events not obstructed by barriers (such as the
++    monitor edge or other pointer barriers).
++
++    To start receiving relative pointer events, a client must first bind the
++    global interface "wp_relative_pointer_manager" which, if a compositor
++    supports relative pointer motion events, is exposed by the registry. After
++    having created the relative pointer manager proxy object, the client uses
++    it to create the actual relative pointer object using the
++    "get_relative_pointer" request given a wl_pointer. The relative pointer
++    motion events will then, when applicable, be transmitted via the proxy of
++    the newly created relative pointer object. See the documentation of the
++    relative pointer interface for more details.
++
++    Warning! The protocol described in this file is experimental and backward
++    incompatible changes may be made. Backward compatible changes may be added
++    together with the corresponding interface version bump. Backward
++    incompatible changes are done by bumping the version number in the protocol
++    and interface names and resetting the interface version. Once the protocol
++    is to be declared stable, the 'z' prefix and the version number in the
++    protocol and interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zwp_relative_pointer_manager_v1" version="1">
++    <description summary="get relative pointer objects">
++      A global interface used for getting the relative pointer object for a
++      given pointer.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the relative pointer manager object">
++      Used by the client to notify the server that it will no longer use this
++      relative pointer manager object.
++      </description>
++    </request>
++
++    <request name="get_relative_pointer">
++      <description summary="get a relative pointer object">
++      Create a relative pointer interface given a wl_pointer object. See the
++      wp_relative_pointer interface for more details.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_relative_pointer_v1"/>
++      <arg name="pointer" type="object" interface="wl_pointer"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_relative_pointer_v1" version="1">
++    <description summary="relative pointer object">
++      A wp_relative_pointer object is an extension to the wl_pointer interface
++      used for emitting relative pointer events. It shares the same focus as
++      wl_pointer objects of the same seat and will only emit events when it has
++      focus.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="release the relative pointer object"/>
++    </request>
++
++    <event name="relative_motion">
++      <description summary="relative pointer motion">
++      Relative x/y pointer motion from the pointer of the seat associated with
++      this object.
++
++      A relative motion is in the same dimension as regular wl_pointer motion
++      events, except they do not represent an absolute position. For example,
++      moving a pointer from (x, y) to (x', y') would have the equivalent
++      relative motion (x' - x, y' - y). If a pointer motion caused the
++      absolute pointer position to be clipped by for example the edge of the
++      monitor, the relative motion is unaffected by the clipping and will
++      represent the unclipped motion.
++
++      This event also contains non-accelerated motion deltas. The
++      non-accelerated delta is, when applicable, the regular pointer motion
++      delta as it was before having applied motion acceleration and other
++      transformations such as normalization.
++
++      Note that the non-accelerated delta does not represent 'raw' events as
++      they were read from some device. Pointer motion acceleration is device-
++      and configuration-specific and non-accelerated deltas and accelerated
++      deltas may have the same value on some devices.
++
++      Relative motions are not coupled to wl_pointer.motion events, and can be
++      sent in combination with such events, but also independently. There may
++      also be scenarios where wl_pointer.motion is sent, but there is no
++      relative motion. The order of an absolute and relative motion event
++      originating from the same physical motion is not guaranteed.
++
++      If the client needs button events or focus state, it can receive them
++      from a wl_pointer object of the same seat that the wp_relative_pointer
++      object is associated with.
++      </description>
++      <arg name="utime_hi" type="uint"
++         summary="high 32 bits of a 64 bit timestamp with microsecond granularity"/>
++      <arg name="utime_lo" type="uint"
++         summary="low 32 bits of a 64 bit timestamp with microsecond granularity"/>
++      <arg name="dx" type="fixed"
++         summary="the x component of the motion vector"/>
++      <arg name="dy" type="fixed"
++         summary="the y component of the motion vector"/>
++      <arg name="dx_unaccel" type="fixed"
++         summary="the x component of the unaccelerated motion vector"/>
++      <arg name="dy_unaccel" type="fixed"
++         summary="the y component of the unaccelerated motion vector"/>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7ba8e77a13a35cea393cd1ce6a9395af16e0576f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Tablet protocol
++
++Maintainers:
++Peter Hutterer <peter.hutterer@who-t.net>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6db9c05a41542216b835594e0ff219eda22ea1bd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,640 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="tablet_unstable_v1">
++
++  <copyright>
++    Copyright 2014 © Stephen "Lyude" Chandler Paul
++    Copyright 2015-2016 © Red Hat, Inc.
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <description summary="Wayland protocol for graphics tablets">
++    This description provides a high-level overview of the interplay between
++    the interfaces defined this protocol. For details, see the protocol
++    specification.
++
++    More than one tablet may exist, and device-specifics matter. Tablets are
++    not represented by a single virtual device like wl_pointer. A client
++    binds to the tablet manager object which is just a proxy object. From
++    that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
++    and that returns the actual interface that has all the tablets. With
++    this indirection, we can avoid merging wp_tablet into the actual Wayland
++    protocol, a long-term benefit.
++
++    The wp_tablet_seat sends a "tablet added" event for each tablet
++    connected. That event is followed by descriptive events about the
++    hardware; currently that includes events for name, vid/pid and
++    a wp_tablet.path event that describes a local path. This path can be
++    used to uniquely identify a tablet or get more information through
++    libwacom. Emulated or nested tablets can skip any of those, e.g. a
++    virtual tablet may not have a vid/pid. The sequence of descriptive
++    events is terminated by a wp_tablet.done event to signal that a client
++    may now finalize any initialization for that tablet.
++
++    Events from tablets require a tool in proximity. Tools are also managed
++    by the tablet seat; a "tool added" event is sent whenever a tool is new
++    to the compositor. That event is followed by a number of descriptive
++    events about the hardware; currently that includes capabilities,
++    hardware id and serial number, and tool type. Similar to the tablet
++    interface, a wp_tablet_tool.done event is sent to terminate that initial
++    sequence.
++
++    Any event from a tool happens on the wp_tablet_tool interface. When the
++    tool gets into proximity of the tablet, a proximity_in event is sent on
++    the wp_tablet_tool interface, listing the tablet and the surface. That
++    event is followed by a motion event with the coordinates. After that,
++    it's the usual motion, axis, button, etc. events. The protocol's
++    serialisation means events are grouped by wp_tablet_tool.frame events.
++
++    Two special events (that don't exist in X) are down and up. They signal
++    "tip touching the surface". For tablets without real proximity
++    detection, the sequence is: proximity_in, motion, down, frame.
++
++    When the tool leaves proximity, a proximity_out event is sent. If any
++    button is still down, a button release event is sent before this
++    proximity event. These button events are sent in the same frame as the
++    proximity event to signal to the client that the buttons were held when
++    the tool left proximity.
++
++    If the tool moves out of the surface but stays in proximity (i.e.
++    between windows), compositor-specific grab policies apply. This usually
++    means that the proximity-out is delayed until all buttons are released.
++
++    Moving a tool physically from one tablet to the other has no real effect
++    on the protocol, since we already have the tool object from the "tool
++    added" event. All the information is already there and the proximity
++    events on both tablets are all a client needs to reconstruct what
++    happened.
++
++    Some extra axes are normalized, i.e. the client knows the range as
++    specified in the protocol (e.g. [0, 65535]), the granularity however is
++    unknown. The current normalized axes are pressure, distance, and slider.
++
++    Other extra axes are in physical units as specified in the protocol.
++    The current extra axes with physical units are tilt, rotation and
++    wheel rotation.
++
++    Since tablets work independently of the pointer controlled by the mouse,
++    the focus handling is independent too and controlled by proximity.
++    The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
++    This cursor surface may be the same as the mouse cursor, and it may be
++    the same across tools but it is possible to be more fine-grained. For
++    example, a client may set different cursors for the pen and eraser.
++
++    Tools are generally independent of tablets and it is
++    compositor-specific policy when a tool can be removed. Common approaches
++    will likely include some form of removing a tool when all tablets the
++    tool was used on are removed.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible changes
++    may be added together with the corresponding interface version bump.
++    Backward incompatible changes are done by bumping the version number in
++    the protocol and interface names and resetting the interface version.
++    Once the protocol is to be declared stable, the 'z' prefix and the
++    version number in the protocol and interface names are removed and the
++    interface version number is reset.
++  </description>
++
++  <interface name="zwp_tablet_manager_v1" version="1">
++    <description summary="controller object for graphic tablet devices">
++      An object that provides access to the graphics tablets available on this
++      system. All tablets are associated with a seat, to get access to the
++      actual tablets, use wp_tablet_manager.get_tablet_seat.
++    </description>
++
++    <request name="get_tablet_seat">
++      <description summary="get the tablet seat">
++      Get the wp_tablet_seat object for the given seat. This object
++      provides access to all graphics tablets in this seat.
++      </description>
++      <arg name="tablet_seat" type="new_id" interface="zwp_tablet_seat_v1"/>
++      <arg name="seat" type="object" interface="wl_seat" summary="The wl_seat object to retrieve the tablets for" />
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="release the memory for the tablet manager object">
++      Destroy the wp_tablet_manager object. Objects created from this
++      object are unaffected and should be destroyed separately.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="zwp_tablet_seat_v1" version="1">
++    <description summary="controller object for graphic tablet devices of a seat">
++      An object that provides access to the graphics tablets available on this
++      seat. After binding to this interface, the compositor sends a set of
++      wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="release the memory for the tablet seat object">
++      Destroy the wp_tablet_seat object. Objects created from this
++      object are unaffected and should be destroyed separately.
++      </description>
++    </request>
++
++    <event name="tablet_added">
++      <description summary="new device notification">
++      This event is sent whenever a new tablet becomes available on this
++      seat. This event only provides the object id of the tablet, any
++      static information about the tablet (device name, vid/pid, etc.) is
++      sent through the wp_tablet interface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_tablet_v1" summary="the newly added graphics tablet"/>
++    </event>
++
++    <event name="tool_added">
++      <description summary="a new tool has been used with a tablet">
++      This event is sent whenever a tool that has not previously been used
++      with a tablet comes into use. This event only provides the object id
++      of the tool; any static information about the tool (capabilities,
++      type, etc.) is sent through the wp_tablet_tool interface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_tablet_tool_v1" summary="the newly added tablet tool"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_tool_v1" version="1">
++    <description summary="a physical tablet tool">
++      An object that represents a physical tool that has been, or is
++      currently in use with a tablet in this seat. Each wp_tablet_tool
++      object stays valid until the client destroys it; the compositor
++      reuses the wp_tablet_tool object to indicate that the object's
++      respective physical tool has come into proximity of a tablet again.
++
++      A wp_tablet_tool object's relation to a physical tool depends on the
++      tablet's ability to report serial numbers. If the tablet supports
++      this capability, then the object represents a specific physical tool
++      and can be identified even when used on multiple tablets.
++
++      A tablet tool has a number of static characteristics, e.g. tool type,
++      hardware_serial and capabilities. These capabilities are sent in an
++      event sequence after the wp_tablet_seat.tool_added event before any
++      actual events from this tool. This initial event sequence is
++      terminated by a wp_tablet_tool.done event.
++
++      Tablet tool events are grouped by wp_tablet_tool.frame events.
++      Any events received before a wp_tablet_tool.frame event should be
++      considered part of the same hardware state change.
++    </description>
++
++    <request name="set_cursor">
++      <description summary="set the tablet tool's surface">
++      Sets the surface of the cursor used for this tool on the given
++      tablet. This request only takes effect if the tool is in proximity
++      of one of the requesting client's surfaces or the surface parameter
++      is the current pointer surface. If there was a previous surface set
++      with this request it is replaced. If surface is NULL, the cursor
++      image is hidden.
++
++      The parameters hotspot_x and hotspot_y define the position of the
++      pointer surface relative to the pointer location. Its top-left corner
++      is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
++      coordinates of the pointer location, in surface-local coordinates.
++
++      On surface.attach requests to the pointer surface, hotspot_x and
++      hotspot_y are decremented by the x and y parameters passed to the
++      request. Attach must be confirmed by wl_surface.commit as usual.
++
++      The hotspot can also be updated by passing the currently set pointer
++      surface to this request with new values for hotspot_x and hotspot_y.
++
++      The current and pending input regions of the wl_surface are cleared,
++      and wl_surface.set_input_region is ignored until the wl_surface is no
++      longer used as the cursor. When the use as a cursor ends, the current
++      and pending input regions become undefined, and the wl_surface is
++      unmapped.
++
++      This request gives the surface the role of a cursor. The role
++      assigned by this request is the same as assigned by
++      wl_pointer.set_cursor meaning the same surface can be
++      used both as a wl_pointer cursor and a wp_tablet cursor. If the
++      surface already has another role, it raises a protocol error.
++      The surface may be used on multiple tablets and across multiple
++      seats.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++      <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++      <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the tool object">
++      This destroys the client's resource for this tool object.
++      </description>
++    </request>
++
++    <enum name="type">
++      <description summary="a physical tool type">
++      Describes the physical type of a tool. The physical type of a tool
++      generally defines its base usage.
++
++      The mouse tool represents a mouse-shaped tool that is not a relative
++      device but bound to the tablet's surface, providing absolute
++      coordinates.
++
++      The lens tool is a mouse-shaped tool with an attached lens to
++      provide precision focus.
++      </description>
++      <entry name="pen" value="0x140" summary="Pen"/>
++      <entry name="eraser" value="0x141" summary="Eraser"/>
++      <entry name="brush" value="0x142" summary="Brush"/>
++      <entry name="pencil" value="0x143" summary="Pencil"/>
++      <entry name="airbrush" value="0x144" summary="Airbrush"/>
++      <entry name="finger" value="0x145" summary="Finger"/>
++      <entry name="mouse" value="0x146" summary="Mouse"/>
++      <entry name="lens" value="0x147" summary="Lens"/>
++    </enum>
++
++    <event name="type">
++      <description summary="tool type">
++      The tool type is the high-level type of the tool and usually decides
++      the interaction expected from this tool.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="tool_type" type="uint" enum="type" summary="the physical tool type"/>
++    </event>
++
++    <event name="hardware_serial">
++      <description summary="unique hardware serial number of the tool">
++      If the physical tool can be identified by a unique 64-bit serial
++      number, this event notifies the client of this serial number.
++
++      If multiple tablets are available in the same seat and the tool is
++      uniquely identifiable by the serial number, that tool may move
++      between tablets.
++
++      Otherwise, if the tool has no serial number and this event is
++      missing, the tool is tied to the tablet it first comes into
++      proximity with. Even if the physical tool is used on multiple
++      tablets, separate wp_tablet_tool objects will be created, one per
++      tablet.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="hardware_serial_hi" type="uint" summary="the unique serial number of the tool, most significant bits"/>
++      <arg name="hardware_serial_lo" type="uint" summary="the unique serial number of the tool, least significant bits"/>
++    </event>
++
++    <event name="hardware_id_wacom">
++      <description summary="hardware id notification in Wacom's format">
++      This event notifies the client of a hardware id available on this tool.
++
++      The hardware id is a device-specific 64-bit id that provides extra
++      information about the tool in use, beyond the wl_tool.type
++      enumeration. The format of the id is specific to tablets made by
++      Wacom Inc. For example, the hardware id of a Wacom Grip
++      Pen (a stylus) is 0x802.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="hardware_id_hi" type="uint" summary="the hardware id, most significant bits"/>
++      <arg name="hardware_id_lo" type="uint" summary="the hardware id, least significant bits"/>
++    </event>
++
++    <enum name="capability">
++      <description summary="capability flags for a tool">
++      Describes extra capabilities on a tablet.
++
++      Any tool must provide x and y values, extra axes are
++      device-specific.
++      </description>
++      <entry name="tilt" value="1" summary="Tilt axes"/>
++      <entry name="pressure" value="2" summary="Pressure axis"/>
++      <entry name="distance" value="3" summary="Distance axis"/>
++      <entry name="rotation" value="4" summary="Z-rotation axis"/>
++      <entry name="slider" value="5" summary="Slider axis"/>
++      <entry name="wheel" value="6" summary="Wheel axis"/>
++    </enum>
++
++    <event name="capability">
++      <description summary="tool capability notification">
++      This event notifies the client of any capabilities of this tool,
++      beyond the main set of x/y axes and tip up/down detection.
++
++      One event is sent for each extra capability available on this tool.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="capability" type="uint" enum="capability" summary="the capability"/>
++    </event>
++
++    <event name="done">
++      <description summary="tool description events sequence complete">
++      This event signals the end of the initial burst of descriptive
++      events. A client may consider the static description of the tool to
++      be complete and finalize initialization of the tool.
++      </description>
++    </event>
++
++    <event name="removed">
++      <description summary="tool removed">
++      This event is sent when the tool is removed from the system and will
++      send no further events. Should the physical tool come back into
++      proximity later, a new wp_tablet_tool object will be created.
++
++      It is compositor-dependent when a tool is removed. A compositor may
++      remove a tool on proximity out, tablet removal or any other reason.
++      A compositor may also keep a tool alive until shutdown.
++
++      If the tool is currently in proximity, a proximity_out event will be
++      sent before the removed event. See wp_tablet_tool.proximity_out for
++      the handling of any buttons logically down.
++
++      When this event is received, the client must wp_tablet_tool.destroy
++      the object.
++      </description>
++    </event>
++
++    <event name="proximity_in">
++      <description summary="proximity in event">
++      Notification that this tool is focused on a certain surface.
++
++      This event can be received when the tool has moved from one surface to
++      another, or when the tool has come back into proximity above the
++      surface.
++
++      If any button is logically down when the tool comes into proximity,
++      the respective button event is sent after the proximity_in event but
++      within the same frame as the proximity_in event.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="tablet" type="object" interface="zwp_tablet_v1" summary="The tablet the tool is in proximity of"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="The current surface the tablet tool is over"/>
++    </event>
++
++    <event name="proximity_out">
++      <description summary="proximity out event">
++      Notification that this tool has either left proximity, or is no
++      longer focused on a certain surface.
++
++      When the tablet tool leaves proximity of the tablet, button release
++      events are sent for each button that was held down at the time of
++      leaving proximity. These events are sent before the proximity_out
++      event but within the same wp_tablet.frame.
++
++      If the tool stays within proximity of the tablet, but the focus
++      changes from one surface to another, a button release event may not
++      be sent until the button is actually released or the tool leaves the
++      proximity of the tablet.
++      </description>
++    </event>
++
++    <event name="down">
++      <description summary="tablet tool is making contact">
++      Sent whenever the tablet tool comes in contact with the surface of the
++      tablet.
++
++      If the tool is already in contact with the tablet when entering the
++      input region, the client owning said region will receive a
++      wp_tablet.proximity_in event, followed by a wp_tablet.down
++      event and a wp_tablet.frame event.
++
++      Note that this event describes logical contact, not physical
++      contact. On some devices, a compositor may not consider a tool in
++      logical contact until a minimum physical pressure threshold is
++      exceeded.
++      </description>
++      <arg name="serial" type="uint"/>
++    </event>
++
++    <event name="up">
++      <description summary="tablet tool is no longer making contact">
++      Sent whenever the tablet tool stops making contact with the surface of
++      the tablet, or when the tablet tool moves out of the input region
++      and the compositor grab (if any) is dismissed.
++
++      If the tablet tool moves out of the input region while in contact
++      with the surface of the tablet and the compositor does not have an
++      ongoing grab on the surface, the client owning said region will
++      receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
++      event and a wp_tablet.frame event. If the compositor has an ongoing
++      grab on this device, this event sequence is sent whenever the grab
++      is dismissed in the future.
++
++      Note that this event describes logical contact, not physical
++      contact. On some devices, a compositor may not consider a tool out
++      of logical contact until physical pressure falls below a specific
++      threshold.
++      </description>
++    </event>
++
++    <event name="motion">
++      <description summary="motion event">
++      Sent whenever a tablet tool moves.
++      </description>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="pressure">
++      <description summary="pressure change event">
++      Sent whenever the pressure axis on a tool changes. The value of this
++      event is normalized to a value between 0 and 65535.
++
++      Note that pressure may be nonzero even when a tool is not in logical
++      contact. See the down and up events for more details.
++      </description>
++      <arg name="pressure" type="uint" summary="The current pressure value"/>
++    </event>
++
++    <event name="distance">
++      <description summary="distance change event">
++      Sent whenever the distance axis on a tool changes. The value of this
++      event is normalized to a value between 0 and 65535.
++
++      Note that distance may be nonzero even when a tool is not in logical
++      contact. See the down and up events for more details.
++      </description>
++      <arg name="distance" type="uint" summary="The current distance value"/>
++    </event>
++
++    <event name="tilt">
++      <description summary="tilt change event">
++      Sent whenever one or both of the tilt axes on a tool change. Each tilt
++      value is in 0.01 of a degree, relative to the z-axis of the tablet.
++      The angle is positive when the top of a tool tilts along the
++      positive x or y axis.
++      </description>
++      <arg name="tilt_x" type="int" summary="The current value of the X tilt axis"/>
++      <arg name="tilt_y" type="int" summary="The current value of the Y tilt axis"/>
++    </event>
++
++    <event name="rotation">
++      <description summary="z-rotation change event">
++      Sent whenever the z-rotation axis on the tool changes. The
++      rotation value is in 0.01 of a degree clockwise from the tool's
++      logical neutral position.
++      </description>
++      <arg name="degrees" type="int" summary="The current rotation of the Z axis"/>
++    </event>
++
++    <event name="slider">
++      <description summary="Slider position change event">
++      Sent whenever the slider position on the tool changes. The
++      value is normalized between -65535 and 65535, with 0 as the logical
++      neutral position of the slider.
++
++      The slider is available on e.g. the Wacom Airbrush tool.
++      </description>
++      <arg name="position" type="int" summary="The current position of slider"/>
++    </event>
++
++    <event name="wheel">
++      <description summary="Wheel delta event">
++      Sent whenever the wheel on the tool emits an event. This event
++      contains two values for the same axis change. The degrees value is
++      in 0.01 of a degree in the same orientation as the
++      wl_pointer.vertical_scroll axis. The clicks value is in discrete
++      logical clicks of the mouse wheel. This value may be zero if the
++      movement of the wheel was less than one logical click.
++
++      Clients should choose either value and avoid mixing degrees and
++      clicks. The compositor may accumulate values smaller than a logical
++      click and emulate click events when a certain threshold is met.
++      Thus, wl_tablet_tool.wheel events with non-zero clicks values may
++      have different degrees values.
++      </description>
++      <arg name="degrees" type="int" summary="The wheel delta in 0.01 of a degree"/>
++      <arg name="clicks" type="int" summary="The wheel delta in discrete clicks"/>
++    </event>
++
++    <enum name="button_state">
++      <description summary="physical button state">
++      Describes the physical state of a button that produced the button event.
++      </description>
++      <entry name="released" value="0" summary="button is not pressed"/>
++      <entry name="pressed" value="1" summary="button is pressed"/>
++    </enum>
++
++    <event name="button">
++      <description summary="button event">
++      Sent whenever a button on the tool is pressed or released.
++
++      If a button is held down when the tool moves in or out of proximity,
++      button events are generated by the compositor. See
++      wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
++      details.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="button" type="uint" summary="The button whose state has changed"/>
++      <arg name="state" type="uint" enum="button_state" summary="Whether the button was pressed or released"/>
++    </event>
++
++    <event name="frame">
++      <description summary="frame event">
++      Marks the end of a series of axis and/or button updates from the
++      tablet. The Wayland protocol requires axis updates to be sent
++      sequentially, however all events within a frame should be considered
++      one hardware event.
++      </description>
++      <arg name="time" type="uint" summary="The time of the event with millisecond granularity"/>
++    </event>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++  </interface>
++
++  <interface name="zwp_tablet_v1" version="1">
++    <description summary="graphics tablet device">
++      The wp_tablet interface represents one graphics tablet device. The
++      tablet interface itself does not generate events; all events are
++      generated by wp_tablet_tool objects when in proximity above a tablet.
++
++      A tablet has a number of static characteristics, e.g. device name and
++      pid/vid. These capabilities are sent in an event sequence after the
++      wp_tablet_seat.tablet_added event. This initial event sequence is
++      terminated by a wp_tablet.done event.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the tablet object">
++      This destroys the client's resource for this tablet object.
++      </description>
++    </request>
++
++    <event name="name">
++      <description summary="tablet device name">
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="name" type="string" summary="the device name"/>
++    </event>
++
++    <event name="id">
++      <description summary="tablet device USB vendor/product id">
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="vid" type="uint" summary="USB vendor id"/>
++      <arg name="pid" type="uint" summary="USB product id"/>
++    </event>
++
++    <event name="path">
++      <description summary="path to the device">
++      A system-specific device path that indicates which device is behind
++      this wp_tablet. This information may be used to gather additional
++      information about the device, e.g. through libwacom.
++
++      A device may have more than one device path. If so, multiple
++      wp_tablet.path events are sent. A device may be emulated and not
++      have a device path, and in that case this event will not be sent.
++
++      The format of the path is unspecified, it may be a device node, a
++      sysfs path, or some other identifier. It is up to the client to
++      identify the string provided.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="path" type="string" summary="path to local device"/>
++    </event>
++
++    <event name="done">
++      <description summary="tablet description events sequence complete">
++      This event is sent immediately to signal the end of the initial
++      burst of descriptive events. A client may consider the static
++      description of the tablet to be complete and finalize initialization
++      of the tablet.
++      </description>
++    </event>
++
++    <event name="removed">
++      <description summary="tablet removed event">
++      Sent when the tablet has been removed from the system. When a tablet
++      is removed, some tools may be removed.
++
++      When this event is received, the client must wp_tablet.destroy
++      the object.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6e4d9a360cb807d111d97b0654cf9f4aa3853f22
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1178 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="tablet_unstable_v2">
++
++  <copyright>
++    Copyright 2014 © Stephen "Lyude" Chandler Paul
++    Copyright 2015-2016 © Red Hat, Inc.
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <description summary="Wayland protocol for graphics tablets">
++    This description provides a high-level overview of the interplay between
++    the interfaces defined this protocol. For details, see the protocol
++    specification.
++
++    More than one tablet may exist, and device-specifics matter. Tablets are
++    not represented by a single virtual device like wl_pointer. A client
++    binds to the tablet manager object which is just a proxy object. From
++    that, the client requests wp_tablet_manager.get_tablet_seat(wl_seat)
++    and that returns the actual interface that has all the tablets. With
++    this indirection, we can avoid merging wp_tablet into the actual Wayland
++    protocol, a long-term benefit.
++
++    The wp_tablet_seat sends a "tablet added" event for each tablet
++    connected. That event is followed by descriptive events about the
++    hardware; currently that includes events for name, vid/pid and
++    a wp_tablet.path event that describes a local path. This path can be
++    used to uniquely identify a tablet or get more information through
++    libwacom. Emulated or nested tablets can skip any of those, e.g. a
++    virtual tablet may not have a vid/pid. The sequence of descriptive
++    events is terminated by a wp_tablet.done event to signal that a client
++    may now finalize any initialization for that tablet.
++
++    Events from tablets require a tool in proximity. Tools are also managed
++    by the tablet seat; a "tool added" event is sent whenever a tool is new
++    to the compositor. That event is followed by a number of descriptive
++    events about the hardware; currently that includes capabilities,
++    hardware id and serial number, and tool type. Similar to the tablet
++    interface, a wp_tablet_tool.done event is sent to terminate that initial
++    sequence.
++
++    Any event from a tool happens on the wp_tablet_tool interface. When the
++    tool gets into proximity of the tablet, a proximity_in event is sent on
++    the wp_tablet_tool interface, listing the tablet and the surface. That
++    event is followed by a motion event with the coordinates. After that,
++    it's the usual motion, axis, button, etc. events. The protocol's
++    serialisation means events are grouped by wp_tablet_tool.frame events.
++
++    Two special events (that don't exist in X) are down and up. They signal
++    "tip touching the surface". For tablets without real proximity
++    detection, the sequence is: proximity_in, motion, down, frame.
++
++    When the tool leaves proximity, a proximity_out event is sent. If any
++    button is still down, a button release event is sent before this
++    proximity event. These button events are sent in the same frame as the
++    proximity event to signal to the client that the buttons were held when
++    the tool left proximity.
++
++    If the tool moves out of the surface but stays in proximity (i.e.
++    between windows), compositor-specific grab policies apply. This usually
++    means that the proximity-out is delayed until all buttons are released.
++
++    Moving a tool physically from one tablet to the other has no real effect
++    on the protocol, since we already have the tool object from the "tool
++    added" event. All the information is already there and the proximity
++    events on both tablets are all a client needs to reconstruct what
++    happened.
++
++    Some extra axes are normalized, i.e. the client knows the range as
++    specified in the protocol (e.g. [0, 65535]), the granularity however is
++    unknown. The current normalized axes are pressure, distance, and slider.
++
++    Other extra axes are in physical units as specified in the protocol.
++    The current extra axes with physical units are tilt, rotation and
++    wheel rotation.
++
++    Since tablets work independently of the pointer controlled by the mouse,
++    the focus handling is independent too and controlled by proximity.
++    The wp_tablet_tool.set_cursor request sets a tool-specific cursor.
++    This cursor surface may be the same as the mouse cursor, and it may be
++    the same across tools but it is possible to be more fine-grained. For
++    example, a client may set different cursors for the pen and eraser.
++
++    Tools are generally independent of tablets and it is
++    compositor-specific policy when a tool can be removed. Common approaches
++    will likely include some form of removing a tool when all tablets the
++    tool was used on are removed.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible changes
++    may be added together with the corresponding interface version bump.
++    Backward incompatible changes are done by bumping the version number in
++    the protocol and interface names and resetting the interface version.
++    Once the protocol is to be declared stable, the 'z' prefix and the
++    version number in the protocol and interface names are removed and the
++    interface version number is reset.
++  </description>
++
++  <interface name="zwp_tablet_manager_v2" version="1">
++    <description summary="controller object for graphic tablet devices">
++      An object that provides access to the graphics tablets available on this
++      system. All tablets are associated with a seat, to get access to the
++      actual tablets, use wp_tablet_manager.get_tablet_seat.
++    </description>
++
++    <request name="get_tablet_seat">
++      <description summary="get the tablet seat">
++      Get the wp_tablet_seat object for the given seat. This object
++      provides access to all graphics tablets in this seat.
++      </description>
++      <arg name="tablet_seat" type="new_id" interface="zwp_tablet_seat_v2"/>
++      <arg name="seat" type="object" interface="wl_seat" summary="The wl_seat object to retrieve the tablets for" />
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="release the memory for the tablet manager object">
++      Destroy the wp_tablet_manager object. Objects created from this
++      object are unaffected and should be destroyed separately.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="zwp_tablet_seat_v2" version="1">
++    <description summary="controller object for graphic tablet devices of a seat">
++      An object that provides access to the graphics tablets available on this
++      seat. After binding to this interface, the compositor sends a set of
++      wp_tablet_seat.tablet_added and wp_tablet_seat.tool_added events.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="release the memory for the tablet seat object">
++      Destroy the wp_tablet_seat object. Objects created from this
++      object are unaffected and should be destroyed separately.
++      </description>
++    </request>
++
++    <event name="tablet_added">
++      <description summary="new device notification">
++      This event is sent whenever a new tablet becomes available on this
++      seat. This event only provides the object id of the tablet, any
++      static information about the tablet (device name, vid/pid, etc.) is
++      sent through the wp_tablet interface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_tablet_v2" summary="the newly added graphics tablet"/>
++    </event>
++
++    <event name="tool_added">
++      <description summary="a new tool has been used with a tablet">
++      This event is sent whenever a tool that has not previously been used
++      with a tablet comes into use. This event only provides the object id
++      of the tool; any static information about the tool (capabilities,
++      type, etc.) is sent through the wp_tablet_tool interface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_tablet_tool_v2" summary="the newly added tablet tool"/>
++    </event>
++
++    <event name="pad_added">
++      <description summary="new pad notification">
++      This event is sent whenever a new pad is known to the system. Typically,
++      pads are physically attached to tablets and a pad_added event is
++      sent immediately after the wp_tablet_seat.tablet_added.
++      However, some standalone pad devices logically attach to tablets at
++      runtime, and the client must wait for wp_tablet_pad.enter to know
++      the tablet a pad is attached to.
++
++      This event only provides the object id of the pad. All further
++      features (buttons, strips, rings) are sent through the wp_tablet_pad
++      interface.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_tablet_pad_v2" summary="the newly added pad"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_tool_v2" version="1">
++    <description summary="a physical tablet tool">
++      An object that represents a physical tool that has been, or is
++      currently in use with a tablet in this seat. Each wp_tablet_tool
++      object stays valid until the client destroys it; the compositor
++      reuses the wp_tablet_tool object to indicate that the object's
++      respective physical tool has come into proximity of a tablet again.
++
++      A wp_tablet_tool object's relation to a physical tool depends on the
++      tablet's ability to report serial numbers. If the tablet supports
++      this capability, then the object represents a specific physical tool
++      and can be identified even when used on multiple tablets.
++
++      A tablet tool has a number of static characteristics, e.g. tool type,
++      hardware_serial and capabilities. These capabilities are sent in an
++      event sequence after the wp_tablet_seat.tool_added event before any
++      actual events from this tool. This initial event sequence is
++      terminated by a wp_tablet_tool.done event.
++
++      Tablet tool events are grouped by wp_tablet_tool.frame events.
++      Any events received before a wp_tablet_tool.frame event should be
++      considered part of the same hardware state change.
++    </description>
++
++    <request name="set_cursor">
++      <description summary="set the tablet tool's surface">
++      Sets the surface of the cursor used for this tool on the given
++      tablet. This request only takes effect if the tool is in proximity
++      of one of the requesting client's surfaces or the surface parameter
++      is the current pointer surface. If there was a previous surface set
++      with this request it is replaced. If surface is NULL, the cursor
++      image is hidden.
++
++      The parameters hotspot_x and hotspot_y define the position of the
++      pointer surface relative to the pointer location. Its top-left corner
++      is always at (x, y) - (hotspot_x, hotspot_y), where (x, y) are the
++      coordinates of the pointer location, in surface-local coordinates.
++
++      On surface.attach requests to the pointer surface, hotspot_x and
++      hotspot_y are decremented by the x and y parameters passed to the
++      request. Attach must be confirmed by wl_surface.commit as usual.
++
++      The hotspot can also be updated by passing the currently set pointer
++      surface to this request with new values for hotspot_x and hotspot_y.
++
++      The current and pending input regions of the wl_surface are cleared,
++      and wl_surface.set_input_region is ignored until the wl_surface is no
++      longer used as the cursor. When the use as a cursor ends, the current
++      and pending input regions become undefined, and the wl_surface is
++      unmapped.
++
++      This request gives the surface the role of a wp_tablet_tool cursor. A
++      surface may only ever be used as the cursor surface for one
++      wp_tablet_tool. If the surface already has another role or has
++      previously been used as cursor surface for a different tool, a
++      protocol error is raised.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
++      <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++      <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the tool object">
++      This destroys the client's resource for this tool object.
++      </description>
++    </request>
++
++    <enum name="type">
++      <description summary="a physical tool type">
++      Describes the physical type of a tool. The physical type of a tool
++      generally defines its base usage.
++
++      The mouse tool represents a mouse-shaped tool that is not a relative
++      device but bound to the tablet's surface, providing absolute
++      coordinates.
++
++      The lens tool is a mouse-shaped tool with an attached lens to
++      provide precision focus.
++      </description>
++      <entry name="pen" value="0x140" summary="Pen"/>
++      <entry name="eraser" value="0x141" summary="Eraser"/>
++      <entry name="brush" value="0x142" summary="Brush"/>
++      <entry name="pencil" value="0x143" summary="Pencil"/>
++      <entry name="airbrush" value="0x144" summary="Airbrush"/>
++      <entry name="finger" value="0x145" summary="Finger"/>
++      <entry name="mouse" value="0x146" summary="Mouse"/>
++      <entry name="lens" value="0x147" summary="Lens"/>
++    </enum>
++
++    <event name="type">
++      <description summary="tool type">
++      The tool type is the high-level type of the tool and usually decides
++      the interaction expected from this tool.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="tool_type" type="uint" enum="type" summary="the physical tool type"/>
++    </event>
++
++    <event name="hardware_serial">
++      <description summary="unique hardware serial number of the tool">
++      If the physical tool can be identified by a unique 64-bit serial
++      number, this event notifies the client of this serial number.
++
++      If multiple tablets are available in the same seat and the tool is
++      uniquely identifiable by the serial number, that tool may move
++      between tablets.
++
++      Otherwise, if the tool has no serial number and this event is
++      missing, the tool is tied to the tablet it first comes into
++      proximity with. Even if the physical tool is used on multiple
++      tablets, separate wp_tablet_tool objects will be created, one per
++      tablet.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="hardware_serial_hi" type="uint" summary="the unique serial number of the tool, most significant bits"/>
++      <arg name="hardware_serial_lo" type="uint" summary="the unique serial number of the tool, least significant bits"/>
++    </event>
++
++    <event name="hardware_id_wacom">
++      <description summary="hardware id notification in Wacom's format">
++      This event notifies the client of a hardware id available on this tool.
++
++      The hardware id is a device-specific 64-bit id that provides extra
++      information about the tool in use, beyond the wl_tool.type
++      enumeration. The format of the id is specific to tablets made by
++      Wacom Inc. For example, the hardware id of a Wacom Grip
++      Pen (a stylus) is 0x802.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="hardware_id_hi" type="uint" summary="the hardware id, most significant bits"/>
++      <arg name="hardware_id_lo" type="uint" summary="the hardware id, least significant bits"/>
++    </event>
++
++    <enum name="capability">
++      <description summary="capability flags for a tool">
++      Describes extra capabilities on a tablet.
++
++      Any tool must provide x and y values, extra axes are
++      device-specific.
++      </description>
++      <entry name="tilt" value="1" summary="Tilt axes"/>
++      <entry name="pressure" value="2" summary="Pressure axis"/>
++      <entry name="distance" value="3" summary="Distance axis"/>
++      <entry name="rotation" value="4" summary="Z-rotation axis"/>
++      <entry name="slider" value="5" summary="Slider axis"/>
++      <entry name="wheel" value="6" summary="Wheel axis"/>
++    </enum>
++
++    <event name="capability">
++      <description summary="tool capability notification">
++      This event notifies the client of any capabilities of this tool,
++      beyond the main set of x/y axes and tip up/down detection.
++
++      One event is sent for each extra capability available on this tool.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_tool.done event.
++      </description>
++      <arg name="capability" type="uint" enum="capability" summary="the capability"/>
++    </event>
++
++    <event name="done">
++      <description summary="tool description events sequence complete">
++      This event signals the end of the initial burst of descriptive
++      events. A client may consider the static description of the tool to
++      be complete and finalize initialization of the tool.
++      </description>
++    </event>
++
++    <event name="removed">
++      <description summary="tool removed">
++      This event is sent when the tool is removed from the system and will
++      send no further events. Should the physical tool come back into
++      proximity later, a new wp_tablet_tool object will be created.
++
++      It is compositor-dependent when a tool is removed. A compositor may
++      remove a tool on proximity out, tablet removal or any other reason.
++      A compositor may also keep a tool alive until shutdown.
++
++      If the tool is currently in proximity, a proximity_out event will be
++      sent before the removed event. See wp_tablet_tool.proximity_out for
++      the handling of any buttons logically down.
++
++      When this event is received, the client must wp_tablet_tool.destroy
++      the object.
++      </description>
++    </event>
++
++    <event name="proximity_in">
++      <description summary="proximity in event">
++      Notification that this tool is focused on a certain surface.
++
++      This event can be received when the tool has moved from one surface to
++      another, or when the tool has come back into proximity above the
++      surface.
++
++      If any button is logically down when the tool comes into proximity,
++      the respective button event is sent after the proximity_in event but
++      within the same frame as the proximity_in event.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="The tablet the tool is in proximity of"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="The current surface the tablet tool is over"/>
++    </event>
++
++    <event name="proximity_out">
++      <description summary="proximity out event">
++      Notification that this tool has either left proximity, or is no
++      longer focused on a certain surface.
++
++      When the tablet tool leaves proximity of the tablet, button release
++      events are sent for each button that was held down at the time of
++      leaving proximity. These events are sent before the proximity_out
++      event but within the same wp_tablet.frame.
++
++      If the tool stays within proximity of the tablet, but the focus
++      changes from one surface to another, a button release event may not
++      be sent until the button is actually released or the tool leaves the
++      proximity of the tablet.
++      </description>
++    </event>
++
++    <event name="down">
++      <description summary="tablet tool is making contact">
++      Sent whenever the tablet tool comes in contact with the surface of the
++      tablet.
++
++      If the tool is already in contact with the tablet when entering the
++      input region, the client owning said region will receive a
++      wp_tablet.proximity_in event, followed by a wp_tablet.down
++      event and a wp_tablet.frame event.
++
++      Note that this event describes logical contact, not physical
++      contact. On some devices, a compositor may not consider a tool in
++      logical contact until a minimum physical pressure threshold is
++      exceeded.
++      </description>
++      <arg name="serial" type="uint"/>
++    </event>
++
++    <event name="up">
++      <description summary="tablet tool is no longer making contact">
++      Sent whenever the tablet tool stops making contact with the surface of
++      the tablet, or when the tablet tool moves out of the input region
++      and the compositor grab (if any) is dismissed.
++
++      If the tablet tool moves out of the input region while in contact
++      with the surface of the tablet and the compositor does not have an
++      ongoing grab on the surface, the client owning said region will
++      receive a wp_tablet.up event, followed by a wp_tablet.proximity_out
++      event and a wp_tablet.frame event. If the compositor has an ongoing
++      grab on this device, this event sequence is sent whenever the grab
++      is dismissed in the future.
++
++      Note that this event describes logical contact, not physical
++      contact. On some devices, a compositor may not consider a tool out
++      of logical contact until physical pressure falls below a specific
++      threshold.
++      </description>
++    </event>
++
++    <event name="motion">
++      <description summary="motion event">
++      Sent whenever a tablet tool moves.
++      </description>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="pressure">
++      <description summary="pressure change event">
++      Sent whenever the pressure axis on a tool changes. The value of this
++      event is normalized to a value between 0 and 65535.
++
++      Note that pressure may be nonzero even when a tool is not in logical
++      contact. See the down and up events for more details.
++      </description>
++      <arg name="pressure" type="uint" summary="The current pressure value"/>
++    </event>
++
++    <event name="distance">
++      <description summary="distance change event">
++      Sent whenever the distance axis on a tool changes. The value of this
++      event is normalized to a value between 0 and 65535.
++
++      Note that distance may be nonzero even when a tool is not in logical
++      contact. See the down and up events for more details.
++      </description>
++      <arg name="distance" type="uint" summary="The current distance value"/>
++    </event>
++
++    <event name="tilt">
++      <description summary="tilt change event">
++      Sent whenever one or both of the tilt axes on a tool change. Each tilt
++      value is in degrees, relative to the z-axis of the tablet.
++      The angle is positive when the top of a tool tilts along the
++      positive x or y axis.
++      </description>
++      <arg name="tilt_x" type="fixed" summary="The current value of the X tilt axis"/>
++      <arg name="tilt_y" type="fixed" summary="The current value of the Y tilt axis"/>
++    </event>
++
++    <event name="rotation">
++      <description summary="z-rotation change event">
++      Sent whenever the z-rotation axis on the tool changes. The
++      rotation value is in degrees clockwise from the tool's
++      logical neutral position.
++      </description>
++      <arg name="degrees" type="fixed" summary="The current rotation of the Z axis"/>
++    </event>
++
++    <event name="slider">
++      <description summary="Slider position change event">
++      Sent whenever the slider position on the tool changes. The
++      value is normalized between -65535 and 65535, with 0 as the logical
++      neutral position of the slider.
++
++      The slider is available on e.g. the Wacom Airbrush tool.
++      </description>
++      <arg name="position" type="int" summary="The current position of slider"/>
++    </event>
++
++    <event name="wheel">
++      <description summary="Wheel delta event">
++      Sent whenever the wheel on the tool emits an event. This event
++      contains two values for the same axis change. The degrees value is
++      in the same orientation as the wl_pointer.vertical_scroll axis. The
++      clicks value is in discrete logical clicks of the mouse wheel. This
++      value may be zero if the movement of the wheel was less
++      than one logical click.
++
++      Clients should choose either value and avoid mixing degrees and
++      clicks. The compositor may accumulate values smaller than a logical
++      click and emulate click events when a certain threshold is met.
++      Thus, wl_tablet_tool.wheel events with non-zero clicks values may
++      have different degrees values.
++      </description>
++      <arg name="degrees" type="fixed" summary="The wheel delta in degrees"/>
++      <arg name="clicks" type="int" summary="The wheel delta in discrete clicks"/>
++    </event>
++
++    <enum name="button_state">
++      <description summary="physical button state">
++      Describes the physical state of a button that produced the button event.
++      </description>
++      <entry name="released" value="0" summary="button is not pressed"/>
++      <entry name="pressed" value="1" summary="button is pressed"/>
++    </enum>
++
++    <event name="button">
++      <description summary="button event">
++      Sent whenever a button on the tool is pressed or released.
++
++      If a button is held down when the tool moves in or out of proximity,
++      button events are generated by the compositor. See
++      wp_tablet_tool.proximity_in and wp_tablet_tool.proximity_out for
++      details.
++      </description>
++      <arg name="serial" type="uint"/>
++      <arg name="button" type="uint" summary="The button whose state has changed"/>
++      <arg name="state" type="uint" enum="button_state" summary="Whether the button was pressed or released"/>
++    </event>
++
++    <event name="frame">
++      <description summary="frame event">
++      Marks the end of a series of axis and/or button updates from the
++      tablet. The Wayland protocol requires axis updates to be sent
++      sequentially, however all events within a frame should be considered
++      one hardware event.
++      </description>
++      <arg name="time" type="uint" summary="The time of the event with millisecond granularity"/>
++    </event>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++  </interface>
++
++  <interface name="zwp_tablet_v2" version="1">
++    <description summary="graphics tablet device">
++      The wp_tablet interface represents one graphics tablet device. The
++      tablet interface itself does not generate events; all events are
++      generated by wp_tablet_tool objects when in proximity above a tablet.
++
++      A tablet has a number of static characteristics, e.g. device name and
++      pid/vid. These capabilities are sent in an event sequence after the
++      wp_tablet_seat.tablet_added event. This initial event sequence is
++      terminated by a wp_tablet.done event.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the tablet object">
++      This destroys the client's resource for this tablet object.
++      </description>
++    </request>
++
++    <event name="name">
++      <description summary="tablet device name">
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="name" type="string" summary="the device name"/>
++    </event>
++
++    <event name="id">
++      <description summary="tablet device USB vendor/product id">
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="vid" type="uint" summary="USB vendor id"/>
++      <arg name="pid" type="uint" summary="USB product id"/>
++    </event>
++
++    <event name="path">
++      <description summary="path to the device">
++      A system-specific device path that indicates which device is behind
++      this wp_tablet. This information may be used to gather additional
++      information about the device, e.g. through libwacom.
++
++      A device may have more than one device path. If so, multiple
++      wp_tablet.path events are sent. A device may be emulated and not
++      have a device path, and in that case this event will not be sent.
++
++      The format of the path is unspecified, it may be a device node, a
++      sysfs path, or some other identifier. It is up to the client to
++      identify the string provided.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet.done event.
++      </description>
++      <arg name="path" type="string" summary="path to local device"/>
++    </event>
++
++    <event name="done">
++      <description summary="tablet description events sequence complete">
++      This event is sent immediately to signal the end of the initial
++      burst of descriptive events. A client may consider the static
++      description of the tablet to be complete and finalize initialization
++      of the tablet.
++      </description>
++    </event>
++
++    <event name="removed">
++      <description summary="tablet removed event">
++      Sent when the tablet has been removed from the system. When a tablet
++      is removed, some tools may be removed.
++
++      When this event is received, the client must wp_tablet.destroy
++      the object.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_pad_ring_v2" version="1">
++    <description summary="pad ring">
++      A circular interaction area, such as the touch ring on the Wacom Intuos
++      Pro series tablets.
++
++      Events on a ring are logically grouped by the wl_tablet_pad_ring.frame
++      event.
++    </description>
++
++    <request name="set_feedback">
++      <description summary="set compositor feedback">
++      Request that the compositor use the provided feedback string
++      associated with this ring. This request should be issued immediately
++      after a wp_tablet_pad_group.mode_switch event from the corresponding
++      group is received, or whenever the ring is mapped to a different
++      action. See wp_tablet_pad_group.mode_switch for more details.
++
++      Clients are encouraged to provide context-aware descriptions for
++      the actions associated with the ring; compositors may use this
++      information to offer visual feedback about the button layout
++      (eg. on-screen displays).
++
++      The provided string 'description' is a UTF-8 encoded string to be
++      associated with this ring, and is considered user-visible; general
++      internationalization rules apply.
++
++      The serial argument will be that of the last
++      wp_tablet_pad_group.mode_switch event received for the group of this
++      ring. Requests providing other serials than the most recent one will be
++      ignored.
++      </description>
++      <arg name="description" type="string" summary="ring description"/>
++      <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the ring object">
++      This destroys the client's resource for this ring object.
++      </description>
++    </request>
++
++    <enum name="source">
++      <description summary="ring axis source">
++      Describes the source types for ring events. This indicates to the
++      client how a ring event was physically generated; a client may
++      adjust the user interface accordingly. For example, events
++      from a "finger" source may trigger kinetic scrolling.
++      </description>
++      <entry name="finger" value="1" summary="finger"/>
++    </enum>
++
++    <event name="source">
++      <description summary="ring event source">
++      Source information for ring events.
++
++      This event does not occur on its own. It is sent before a
++      wp_tablet_pad_ring.frame event and carries the source information
++      for all events within that frame.
++
++      The source specifies how this event was generated. If the source is
++      wp_tablet_pad_ring.source.finger, a wp_tablet_pad_ring.stop event
++      will be sent when the user lifts the finger off the device.
++
++      This event is optional. If the source is unknown for an interaction,
++      no event is sent.
++      </description>
++      <arg name="source" type="uint" enum="source" summary="the event source"/>
++    </event>
++
++    <event name="angle">
++      <description summary="angle changed">
++      Sent whenever the angle on a ring changes.
++
++      The angle is provided in degrees clockwise from the logical
++      north of the ring in the pad's current rotation.
++      </description>
++      <arg name="degrees" type="fixed" summary="the current angle in degrees"/>
++    </event>
++
++    <event name="stop">
++      <description summary="interaction stopped">
++      Stop notification for ring events.
++
++      For some wp_tablet_pad_ring.source types, a wp_tablet_pad_ring.stop
++      event is sent to notify a client that the interaction with the ring
++      has terminated. This enables the client to implement kinetic scrolling.
++      See the wp_tablet_pad_ring.source documentation for information on
++      when this event may be generated.
++
++      Any wp_tablet_pad_ring.angle events with the same source after this
++      event should be considered as the start of a new interaction.
++      </description>
++    </event>
++
++    <event name="frame">
++      <description summary="end of a ring event sequence">
++      Indicates the end of a set of ring events that logically belong
++      together. A client is expected to accumulate the data in all events
++      within the frame before proceeding.
++
++      All wp_tablet_pad_ring events before a wp_tablet_pad_ring.frame event belong
++      logically together. For example, on termination of a finger interaction
++      on a ring the compositor will send a wp_tablet_pad_ring.source event,
++      a wp_tablet_pad_ring.stop event and a wp_tablet_pad_ring.frame event.
++
++      A wp_tablet_pad_ring.frame event is sent for every logical event
++      group, even if the group only contains a single wp_tablet_pad_ring
++      event. Specifically, a client may get a sequence: angle, frame,
++      angle, frame, etc.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_pad_strip_v2" version="1">
++    <description summary="pad strip">
++      A linear interaction area, such as the strips found in Wacom Cintiq
++      models.
++
++      Events on a strip are logically grouped by the wl_tablet_pad_strip.frame
++      event.
++    </description>
++
++    <request name="set_feedback">
++      <description summary="set compositor feedback">
++      Requests the compositor to use the provided feedback string
++      associated with this strip. This request should be issued immediately
++      after a wp_tablet_pad_group.mode_switch event from the corresponding
++      group is received, or whenever the strip is mapped to a different
++      action. See wp_tablet_pad_group.mode_switch for more details.
++
++      Clients are encouraged to provide context-aware descriptions for
++      the actions associated with the strip, and compositors may use this
++      information to offer visual feedback about the button layout
++      (eg. on-screen displays).
++
++      The provided string 'description' is a UTF-8 encoded string to be
++      associated with this ring, and is considered user-visible; general
++      internationalization rules apply.
++
++      The serial argument will be that of the last
++      wp_tablet_pad_group.mode_switch event received for the group of this
++      strip. Requests providing other serials than the most recent one will be
++      ignored.
++      </description>
++      <arg name="description" type="string" summary="strip description"/>
++      <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the strip object">
++      This destroys the client's resource for this strip object.
++      </description>
++    </request>
++
++    <enum name="source">
++      <description summary="strip axis source">
++      Describes the source types for strip events. This indicates to the
++      client how a strip event was physically generated; a client may
++      adjust the user interface accordingly. For example, events
++      from a "finger" source may trigger kinetic scrolling.
++      </description>
++      <entry name="finger" value="1" summary="finger"/>
++    </enum>
++
++    <event name="source">
++      <description summary="strip event source">
++      Source information for strip events.
++
++      This event does not occur on its own. It is sent before a
++      wp_tablet_pad_strip.frame event and carries the source information
++      for all events within that frame.
++
++      The source specifies how this event was generated. If the source is
++      wp_tablet_pad_strip.source.finger, a wp_tablet_pad_strip.stop event
++      will be sent when the user lifts their finger off the device.
++
++      This event is optional. If the source is unknown for an interaction,
++      no event is sent.
++      </description>
++      <arg name="source" type="uint" enum="source" summary="the event source"/>
++    </event>
++
++    <event name="position">
++      <description summary="position changed">
++      Sent whenever the position on a strip changes.
++
++      The position is normalized to a range of [0, 65535], the 0-value
++      represents the top-most and/or left-most position of the strip in
++      the pad's current rotation.
++      </description>
++      <arg name="position" type="uint" summary="the current position"/>
++    </event>
++
++    <event name="stop">
++      <description summary="interaction stopped">
++      Stop notification for strip events.
++
++      For some wp_tablet_pad_strip.source types, a wp_tablet_pad_strip.stop
++      event is sent to notify a client that the interaction with the strip
++      has terminated. This enables the client to implement kinetic
++      scrolling. See the wp_tablet_pad_strip.source documentation for
++      information on when this event may be generated.
++
++      Any wp_tablet_pad_strip.position events with the same source after this
++      event should be considered as the start of a new interaction.
++      </description>
++    </event>
++
++    <event name="frame">
++      <description summary="end of a strip event sequence">
++      Indicates the end of a set of events that represent one logical
++      hardware strip event. A client is expected to accumulate the data
++      in all events within the frame before proceeding.
++
++      All wp_tablet_pad_strip events before a wp_tablet_pad_strip.frame event belong
++      logically together. For example, on termination of a finger interaction
++      on a strip the compositor will send a wp_tablet_pad_strip.source event,
++      a wp_tablet_pad_strip.stop event and a wp_tablet_pad_strip.frame
++      event.
++
++      A wp_tablet_pad_strip.frame event is sent for every logical event
++      group, even if the group only contains a single wp_tablet_pad_strip
++      event. Specifically, a client may get a sequence: position, frame,
++      position, frame, etc.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_pad_group_v2" version="1">
++    <description summary="a set of buttons, rings and strips">
++      A pad group describes a distinct (sub)set of buttons, rings and strips
++      present in the tablet. The criteria of this grouping is usually positional,
++      eg. if a tablet has buttons on the left and right side, 2 groups will be
++      presented. The physical arrangement of groups is undisclosed and may
++      change on the fly.
++
++      Pad groups will announce their features during pad initialization. Between
++      the corresponding wp_tablet_pad.group event and wp_tablet_pad_group.done, the
++      pad group will announce the buttons, rings and strips contained in it,
++      plus the number of supported modes.
++
++      Modes are a mechanism to allow multiple groups of actions for every element
++      in the pad group. The number of groups and available modes in each is
++      persistent across device plugs. The current mode is user-switchable, it
++      will be announced through the wp_tablet_pad_group.mode_switch event both
++      whenever it is switched, and after wp_tablet_pad.enter.
++
++      The current mode logically applies to all elements in the pad group,
++      although it is at clients' discretion whether to actually perform different
++      actions, and/or issue the respective .set_feedback requests to notify the
++      compositor. See the wp_tablet_pad_group.mode_switch event for more details.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pad object">
++      Destroy the wp_tablet_pad_group object. Objects created from this object
++      are unaffected and should be destroyed separately.
++      </description>
++    </request>
++
++    <event name="buttons">
++      <description summary="buttons announced">
++      Sent on wp_tablet_pad_group initialization to announce the available
++      buttons in the group. Button indices start at 0, a button may only be
++      in one group at a time.
++
++      This event is first sent in the initial burst of events before the
++      wp_tablet_pad_group.done event.
++
++      Some buttons are reserved by the compositor. These buttons may not be
++      assigned to any wp_tablet_pad_group. Compositors may broadcast this
++      event in the case of changes to the mapping of these reserved buttons.
++      If the compositor happens to reserve all buttons in a group, this event
++      will be sent with an empty array.
++      </description>
++      <arg name="buttons" type="array" summary="buttons in this group"/>
++    </event>
++
++    <event name="ring">
++      <description summary="ring announced">
++      Sent on wp_tablet_pad_group initialization to announce available rings.
++      One event is sent for each ring available on this pad group.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad_group.done event.
++      </description>
++      <arg name="ring" type="new_id" interface="zwp_tablet_pad_ring_v2"/>
++    </event>
++
++    <event name="strip">
++      <description summary="strip announced">
++      Sent on wp_tablet_pad initialization to announce available strips.
++      One event is sent for each strip available on this pad group.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad_group.done event.
++      </description>
++      <arg name="strip" type="new_id" interface="zwp_tablet_pad_strip_v2"/>
++    </event>
++
++    <event name="modes">
++      <description summary="mode-switch ability announced">
++      Sent on wp_tablet_pad_group initialization to announce that the pad
++      group may switch between modes. A client may use a mode to store a
++      specific configuration for buttons, rings and strips and use the
++      wl_tablet_pad_group.mode_switch event to toggle between these
++      configurations. Mode indices start at 0.
++
++      Switching modes is compositor-dependent. See the
++      wp_tablet_pad_group.mode_switch event for more details.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad_group.done event. This event is only sent when more than
++      more than one mode is available.
++      </description>
++      <arg name="modes" type="uint" summary="the number of modes"/>
++    </event>
++
++    <event name="done">
++      <description summary="tablet group description events sequence complete">
++      This event is sent immediately to signal the end of the initial
++      burst of descriptive events. A client may consider the static
++      description of the tablet to be complete and finalize initialization
++      of the tablet group.
++      </description>
++    </event>
++
++    <event name="mode_switch">
++      <description summary="mode switch event">
++      Notification that the mode was switched.
++
++      A mode applies to all buttons, rings and strips in a group
++      simultaneously, but a client is not required to assign different actions
++      for each mode. For example, a client may have mode-specific button
++      mappings but map the ring to vertical scrolling in all modes. Mode
++      indices start at 0.
++
++      Switching modes is compositor-dependent. The compositor may provide
++      visual cues to the client about the mode, e.g. by toggling LEDs on
++      the tablet device. Mode-switching may be software-controlled or
++      controlled by one or more physical buttons. For example, on a Wacom
++      Intuos Pro, the button inside the ring may be assigned to switch
++      between modes.
++
++      The compositor will also send this event after wp_tablet_pad.enter on
++      each group in order to notify of the current mode. Groups that only
++      feature one mode will use mode=0 when emitting this event.
++
++      If a button action in the new mode differs from the action in the
++      previous mode, the client should immediately issue a
++      wp_tablet_pad.set_feedback request for each changed button.
++
++      If a ring or strip action in the new mode differs from the action
++      in the previous mode, the client should immediately issue a
++      wp_tablet_ring.set_feedback or wp_tablet_strip.set_feedback request
++      for each changed ring or strip.
++      </description>
++      <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
++      <arg name="serial" type="uint"/>
++      <arg name="mode" type="uint" summary="the new mode of the pad"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_tablet_pad_v2" version="1">
++    <description summary="a set of buttons, rings and strips">
++      A pad device is a set of buttons, rings and strips
++      usually physically present on the tablet device itself. Some
++      exceptions exist where the pad device is physically detached, e.g. the
++      Wacom ExpressKey Remote.
++
++      Pad devices have no axes that control the cursor and are generally
++      auxiliary devices to the tool devices used on the tablet surface.
++
++      A pad device has a number of static characteristics, e.g. the number
++      of rings. These capabilities are sent in an event sequence after the
++      wp_tablet_seat.pad_added event before any actual events from this pad.
++      This initial event sequence is terminated by a wp_tablet_pad.done
++      event.
++
++      All pad features (buttons, rings and strips) are logically divided into
++      groups and all pads have at least one group. The available groups are
++      notified through the wp_tablet_pad.group event; the compositor will
++      emit one event per group before emitting wp_tablet_pad.done.
++
++      Groups may have multiple modes. Modes allow clients to map multiple
++      actions to a single pad feature. Only one mode can be active per group,
++      although different groups may have different active modes.
++    </description>
++
++    <request name="set_feedback">
++      <description summary="set compositor feedback">
++      Requests the compositor to use the provided feedback string
++      associated with this button. This request should be issued immediately
++      after a wp_tablet_pad_group.mode_switch event from the corresponding
++      group is received, or whenever a button is mapped to a different
++      action. See wp_tablet_pad_group.mode_switch for more details.
++
++      Clients are encouraged to provide context-aware descriptions for
++      the actions associated with each button, and compositors may use
++      this information to offer visual feedback on the button layout
++      (e.g. on-screen displays).
++
++      Button indices start at 0. Setting the feedback string on a button
++      that is reserved by the compositor (i.e. not belonging to any
++      wp_tablet_pad_group) does not generate an error but the compositor
++      is free to ignore the request.
++
++      The provided string 'description' is a UTF-8 encoded string to be
++      associated with this ring, and is considered user-visible; general
++      internationalization rules apply.
++
++      The serial argument will be that of the last
++      wp_tablet_pad_group.mode_switch event received for the group of this
++      button. Requests providing other serials than the most recent one will
++      be ignored.
++      </description>
++      <arg name="button" type="uint" summary="button index"/>
++      <arg name="description" type="string" summary="button description"/>
++      <arg name="serial" type="uint" summary="serial of the mode switch event"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pad object">
++      Destroy the wp_tablet_pad object. Objects created from this object
++      are unaffected and should be destroyed separately.
++      </description>
++    </request>
++
++    <event name="group">
++      <description summary="group announced">
++      Sent on wp_tablet_pad initialization to announce available groups.
++      One event is sent for each pad group available.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad.done event. At least one group will be announced.
++      </description>
++      <arg name="pad_group" type="new_id" interface="zwp_tablet_pad_group_v2"/>
++    </event>
++
++    <event name="path">
++      <description summary="path to the device">
++      A system-specific device path that indicates which device is behind
++      this wp_tablet_pad. This information may be used to gather additional
++      information about the device, e.g. through libwacom.
++
++      The format of the path is unspecified, it may be a device node, a
++      sysfs path, or some other identifier. It is up to the client to
++      identify the string provided.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad.done event.
++      </description>
++      <arg name="path" type="string" summary="path to local device"/>
++    </event>
++
++    <event name="buttons">
++      <description summary="buttons announced">
++      Sent on wp_tablet_pad initialization to announce the available
++      buttons.
++
++      This event is sent in the initial burst of events before the
++      wp_tablet_pad.done event. This event is only sent when at least one
++      button is available.
++      </description>
++      <arg name="buttons" type="uint" summary="the number of buttons"/>
++    </event>
++
++    <event name="done">
++      <description summary="pad description event sequence complete">
++      This event signals the end of the initial burst of descriptive
++      events. A client may consider the static description of the pad to
++      be complete and finalize initialization of the pad.
++      </description>
++    </event>
++
++    <enum name="button_state">
++      <description summary="physical button state">
++      Describes the physical state of a button that caused the button
++      event.
++      </description>
++      <entry name="released" value="0" summary="the button is not pressed"/>
++      <entry name="pressed" value="1" summary="the button is pressed"/>
++    </enum>
++
++    <event name="button">
++      <description summary="physical button state">
++      Sent whenever the physical state of a button changes.
++      </description>
++      <arg name="time" type="uint" summary="the time of the event with millisecond granularity"/>
++      <arg name="button" type="uint" summary="the index of the button that changed state"/>
++      <arg name="state" type="uint" enum="button_state"/>
++    </event>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notification that this pad is focused on the specified surface.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="tablet" type="object" interface="zwp_tablet_v2" summary="the tablet the pad is attached to"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is focused on"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notification that this pad is no longer focused on the specified
++      surface.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the leave event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface the pad is no longer focused on"/>
++    </event>
++
++    <event name="removed">
++      <description summary="pad removed event">
++      Sent when the pad has been removed from the system. When a tablet
++      is removed its pad(s) will be removed too.
++
++      When this event is received, the client must destroy all rings, strips
++      and groups that were offered by this pad, and issue wp_tablet_pad.destroy
++      the pad itself.
++      </description>
++    </event>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..afa4bacf521de6847f9a98eb6aadbab5f8e5f7ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Text input protocol
++
++Maintainers:
++Jan Arne Petersen <janarne@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6ee266522a5cd60219a25672451743c8b7c430cc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,385 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="text_input_unstable_v1">
++
++  <copyright>
++    Copyright © 2012, 2013 Intel Corporation
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zwp_text_input_v1" version="1">
++    <description summary="text input">
++      An object used for text input. Adds support for text input and input
++      methods to applications. A text_input object is created from a
++      wl_text_input_manager and corresponds typically to a text entry in an
++      application.
++
++      Requests are used to activate/deactivate the text_input object and set
++      state information like surrounding and selected text or the content type.
++      The information about entered text is sent to the text_input object via
++      the pre-edit and commit events. Using this interface removes the need
++      for applications to directly process hardware key events and compose text
++      out of them.
++
++      Text is generally UTF-8 encoded, indices and lengths are in bytes.
++
++      Serials are used to synchronize the state between the text input and
++      an input method. New serials are sent by the text input in the
++      commit_state request and are used by the input method to indicate
++      the known text input state in events like preedit_string, commit_string,
++      and keysym. The text input can then ignore events from the input method
++      which are based on an outdated state (for example after a reset).
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="activate">
++      <description summary="request activation">
++      Requests the text_input object to be activated (typically when the
++      text entry gets focus).
++
++      The seat argument is a wl_seat which maintains the focus for this
++      activation. The surface argument is a wl_surface assigned to the
++      text_input object and tracked for focus lost. The enter event
++      is emitted on successful activation.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++
++    <request name="deactivate">
++      <description summary="request deactivation">
++      Requests the text_input object to be deactivated (typically when the
++      text entry lost focus). The seat argument is a wl_seat which was used
++      for activation.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat"/>
++    </request>
++
++    <request name="show_input_panel">
++      <description summary="show input panels">
++      Requests input panels (virtual keyboard) to show.
++      </description>
++    </request>
++
++    <request name="hide_input_panel">
++      <description summary="hide input panels">
++      Requests input panels (virtual keyboard) to hide.
++      </description>
++    </request>
++
++    <request name="reset">
++      <description summary="reset">
++      Should be called by an editor widget when the input state should be
++      reset, for example after the text was changed outside of the normal
++      input method flow.
++      </description>
++    </request>
++
++    <request name="set_surrounding_text">
++      <description summary="sets the surrounding text">
++      Sets the plain surrounding text around the input position. Text is
++      UTF-8 encoded. Cursor is the byte offset within the
++      surrounding text. Anchor is the byte offset of the
++      selection anchor within the surrounding text. If there is no selected
++      text anchor, then it is the same as cursor.
++      </description>
++      <arg name="text" type="string"/>
++      <arg name="cursor" type="uint"/>
++      <arg name="anchor" type="uint"/>
++    </request>
++
++    <enum name="content_hint" bitfield="true">
++      <description summary="content hint">
++      Content hint is a bitmask to allow to modify the behavior of the text
++      input.
++      </description>
++      <entry name="none" value="0x0" summary="no special behaviour"/>
++      <entry name="default" value="0x7" summary="auto completion, correction and capitalization"/>
++      <entry name="password" value="0xc0" summary="hidden and sensitive text"/>
++      <entry name="auto_completion" value="0x1" summary="suggest word completions"/>
++      <entry name="auto_correction" value="0x2" summary="suggest word corrections"/>
++      <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
++      <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
++      <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
++      <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
++      <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
++      <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
++      <entry name="latin" value="0x100" summary="just latin characters should be entered"/>
++      <entry name="multiline" value="0x200" summary="the text input is multiline"/>
++    </enum>
++
++    <enum name="content_purpose">
++      <description summary="content purpose">
++      The content purpose allows to specify the primary purpose of a text
++      input.
++
++      This allows an input method to show special purpose input panels with
++      extra characters or to disallow some characters.
++      </description>
++      <entry name="normal" value="0" summary="default input, allowing all characters"/>
++      <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
++      <entry name="digits" value="2" summary="allow only digits"/>
++      <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
++      <entry name="phone" value="4" summary="input a phone number"/>
++      <entry name="url" value="5" summary="input an URL"/>
++      <entry name="email" value="6" summary="input an email address"/>
++      <entry name="name" value="7" summary="input a name of a person"/>
++      <entry name="password" value="8" summary="input a password (combine with password or sensitive_data hint)"/>
++      <entry name="date" value="9" summary="input a date"/>
++      <entry name="time" value="10" summary="input a time"/>
++      <entry name="datetime" value="11" summary="input a date and time"/>
++      <entry name="terminal" value="12" summary="input for a terminal"/>
++    </enum>
++
++    <request name="set_content_type">
++      <description summary="set content purpose and hint">
++      Sets the content purpose and content hint. While the purpose is the
++      basic purpose of an input field, the hint flags allow to modify some
++      of the behavior.
++
++      When no content type is explicitly set, a normal content purpose with
++      default hints (auto completion, auto correction, auto capitalization)
++      should be assumed.
++      </description>
++      <arg name="hint" type="uint" enum="content_hint" />
++      <arg name="purpose" type="uint" enum="content_purpose" />
++    </request>
++
++    <request name="set_cursor_rectangle">
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_preferred_language">
++      <description summary="sets preferred language">
++      Sets a specific language. This allows for example a virtual keyboard to
++      show a language specific layout. The "language" argument is an RFC-3066
++      format language tag.
++
++      It could be used for example in a word processor to indicate the
++      language of the currently edited document or in an instant message
++      application which tracks languages of contacts.
++      </description>
++      <arg name="language" type="string"/>
++    </request>
++
++    <request name="commit_state">
++      <arg name="serial" type="uint" summary="used to identify the known state"/>
++    </request>
++
++    <request name="invoke_action">
++      <arg name="button" type="uint"/>
++      <arg name="index" type="uint"/>
++    </request>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notify the text_input object when it received focus. Typically in
++      response to an activate request.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notify the text_input object when it lost focus. Either in response
++      to a deactivate request or when the assigned surface lost focus or was
++      destroyed.
++      </description>
++    </event>
++
++    <event name="modifiers_map">
++      <description summary="modifiers map">
++      Transfer an array of 0-terminated modifier names. The position in
++      the array is the index of the modifier as used in the modifiers
++      bitmask in the keysym event.
++      </description>
++      <arg name="map" type="array"/>
++    </event>
++
++    <event name="input_panel_state">
++      <description summary="state of the input panel">
++      Notify when the visibility state of the input panel changed.
++      </description>
++      <arg name="state" type="uint"/>
++    </event>
++
++    <event name="preedit_string">
++      <description summary="pre-edit">
++      Notify when a new composing text (pre-edit) should be set around the
++      current cursor position. Any previously set composing text should
++      be removed.
++
++      The commit text can be used to replace the preedit text on reset
++      (for example on unfocus).
++
++      The text input should also handle all preedit_style and preedit_cursor
++      events occurring directly before preedit_string.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="text" type="string"/>
++      <arg name="commit" type="string"/>
++    </event>
++
++    <enum name="preedit_style">
++      <entry name="default" value="0" summary="default style for composing text"/>
++      <entry name="none" value="1" summary="style should be the same as in non-composing text"/>
++      <entry name="active" value="2"/>
++      <entry name="inactive" value="3"/>
++      <entry name="highlight" value="4"/>
++      <entry name="underline" value="5"/>
++      <entry name="selection" value="6"/>
++      <entry name="incorrect" value="7"/>
++    </enum>
++
++    <event name="preedit_styling">
++      <description summary="pre-edit styling">
++      Sets styling information on composing text. The style is applied for
++      length bytes from index relative to the beginning of the composing
++      text (as byte offset). Multiple styles can
++      be applied to a composing text by sending multiple preedit_styling
++      events.
++
++      This event is handled as part of a following preedit_string event.
++      </description>
++      <arg name="index" type="uint"/>
++      <arg name="length" type="uint"/>
++      <arg name="style" type="uint" enum="preedit_style" />
++    </event>
++
++    <event name="preedit_cursor">
++      <description summary="pre-edit cursor">
++      Sets the cursor position inside the composing text (as byte
++      offset) relative to the start of the composing text. When index is a
++      negative number no cursor is shown.
++
++      This event is handled as part of a following preedit_string event.
++      </description>
++      <arg name="index" type="int"/>
++    </event>
++
++    <event name="commit_string">
++      <description summary="commit">
++      Notify when text should be inserted into the editor widget. The text to
++      commit could be either just a single character after a key press or the
++      result of some composing (pre-edit). It could also be an empty text
++      when some text should be removed (see delete_surrounding_text) or when
++      the input cursor should be moved (see cursor_position).
++
++      Any previously set composing text should be removed.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="text" type="string"/>
++    </event>
++
++    <event name="cursor_position">
++      <description summary="set cursor to new position">
++      Notify when the cursor or anchor position should be modified.
++
++      This event should be handled as part of a following commit_string
++      event.
++      </description>
++      <arg name="index" type="int"/>
++      <arg name="anchor" type="int"/>
++    </event>
++
++    <event name="delete_surrounding_text">
++      <description summary="delete surrounding text">
++      Notify when the text around the current cursor position should be
++      deleted.
++
++      Index is relative to the current cursor (in bytes).
++      Length is the length of deleted text (in bytes).
++
++      This event should be handled as part of a following commit_string
++      event.
++      </description>
++      <arg name="index" type="int"/>
++      <arg name="length" type="uint"/>
++    </event>
++
++    <event name="keysym">
++      <description summary="keysym">
++      Notify when a key event was sent. Key events should not be used
++      for normal text input operations, which should be done with
++      commit_string, delete_surrounding_text, etc. The key event follows
++      the wl_keyboard key event convention. Sym is an XKB keysym, state a
++      wl_keyboard key_state. Modifiers are a mask for effective modifiers
++      (where the modifier indices are set by the modifiers_map event)
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="time" type="uint"/>
++      <arg name="sym" type="uint"/>
++      <arg name="state" type="uint"/>
++      <arg name="modifiers" type="uint"/>
++    </event>
++
++    <event name="language">
++      <description summary="language">
++      Sets the language of the input text. The "language" argument is an
++      RFC-3066 format language tag.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="language" type="string"/>
++    </event>
++
++    <enum name="text_direction">
++      <entry name="auto" value="0" summary="automatic text direction based on text and language"/>
++      <entry name="ltr" value="1" summary="left-to-right"/>
++      <entry name="rtl" value="2" summary="right-to-left"/>
++    </enum>
++
++    <event name="text_direction">
++      <description summary="text direction">
++      Sets the text direction of input text.
++
++      It is mainly needed for showing an input cursor on the correct side of
++      the editor when there is no input done yet and making sure neutral
++      direction text is laid out properly.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the latest known text input state"/>
++      <arg name="direction" type="uint" enum="text_direction" />
++    </event>
++  </interface>
++
++  <interface name="zwp_text_input_manager_v1" version="1">
++    <description summary="text input manager">
++      A factory for text_input objects. This object is a global singleton.
++    </description>
++
++    <request name="create_text_input">
++      <description summary="create text input">
++      Creates a new text_input object.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_text_input_v1"/>
++    </request>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1fae54d7ba7617a2e218835ec56f4813161df3af
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,457 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++
++<protocol name="text_input_unstable_v3">
++  <copyright>
++    Copyright © 2012, 2013 Intel Corporation
++    Copyright © 2015, 2016 Jan Arne Petersen
++    Copyright © 2017, 2018 Red Hat, Inc.
++    Copyright © 2018       Purism SPC
++
++    Permission to use, copy, modify, distribute, and sell this
++    software and its documentation for any purpose is hereby granted
++    without fee, provided that the above copyright notice appear in
++    all copies and that both that copyright notice and this permission
++    notice appear in supporting documentation, and that the name of
++    the copyright holders not be used in advertising or publicity
++    pertaining to distribution of the software without specific,
++    written prior permission.  The copyright holders make no
++    representations about the suitability of this software for any
++    purpose.  It is provided "as is" without express or implied
++    warranty.
++
++    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
++    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
++    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
++    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
++    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
++    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
++    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
++    THIS SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for composing text">
++    This protocol allows compositors to act as input methods and to send text
++    to applications. A text input object is used to manage state of what are
++    typically text entry fields in the application.
++
++    This document adheres to the RFC 2119 when using words like "must",
++    "should", "may", etc.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible changes
++    may be added together with the corresponding interface version bump.
++    Backward incompatible changes are done by bumping the version number in
++    the protocol and interface names and resetting the interface version.
++    Once the protocol is to be declared stable, the 'z' prefix and the
++    version number in the protocol and interface names are removed and the
++    interface version number is reset.
++  </description>
++
++  <interface name="zwp_text_input_v3" version="1">
++    <description summary="text input">
++      The zwp_text_input_v3 interface represents text input and input methods
++      associated with a seat. It provides enter/leave events to follow the
++      text input focus for a seat.
++
++      Requests are used to enable/disable the text-input object and set
++      state information like surrounding and selected text or the content type.
++      The information about the entered text is sent to the text-input object
++      via the preedit_string and commit_string events.
++
++      Text is valid UTF-8 encoded, indices and lengths are in bytes. Indices
++      must not point to middle bytes inside a code point: they must either
++      point to the first byte of a code point or to the end of the buffer.
++      Lengths must be measured between two valid indices.
++
++      Focus moving throughout surfaces will result in the emission of
++      zwp_text_input_v3.enter and zwp_text_input_v3.leave events. The focused
++      surface must commit zwp_text_input_v3.enable and
++      zwp_text_input_v3.disable requests as the keyboard focus moves across
++      editable and non-editable elements of the UI. Those two requests are not
++      expected to be paired with each other, the compositor must be able to
++      handle consecutive series of the same request.
++
++      State is sent by the state requests (set_surrounding_text,
++      set_content_type and set_cursor_rectangle) and a commit request. After an
++      enter event or disable request all state information is invalidated and
++      needs to be resent by the client.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="Destroy the wp_text_input">
++        Destroy the wp_text_input object. Also disables all surfaces enabled
++        through this wp_text_input object.
++      </description>
++    </request>
++
++    <request name="enable">
++      <description summary="Request text input to be enabled">
++        Requests text input on the surface previously obtained from the enter
++        event.
++
++        This request must be issued every time the active text input changes
++        to a new one, including within the current surface. Use
++        zwp_text_input_v3.disable when there is no longer any input focus on
++        the current surface.
++
++        Clients must not enable more than one text input on the single seat
++        and should disable the current text input before enabling the new one.
++        At most one instance of text input may be in enabled state per instance,
++        Requests to enable the another text input when some text input is active
++        must be ignored by compositor.
++
++        This request resets all state associated with previous enable, disable,
++        set_surrounding_text, set_text_change_cause, set_content_type, and
++        set_cursor_rectangle requests, as well as the state associated with
++        preedit_string, commit_string, and delete_surrounding_text events.
++
++        The set_surrounding_text, set_content_type and set_cursor_rectangle
++        requests must follow if the text input supports the necessary
++        functionality.
++
++        State set with this request is double-buffered. It will get applied on
++        the next zwp_text_input_v3.commit request, and stay valid until the
++        next committed enable or disable request.
++
++        The changes must be applied by the compositor after issuing a
++        zwp_text_input_v3.commit request.
++      </description>
++    </request>
++
++    <request name="disable">
++      <description summary="Disable text input on a surface">
++        Explicitly disable text input on the current surface (typically when
++        there is no focus on any text entry inside the surface).
++
++        State set with this request is double-buffered. It will get applied on
++        the next zwp_text_input_v3.commit request.
++      </description>
++    </request>
++
++    <request name="set_surrounding_text">
++      <description summary="sets the surrounding text">
++        Sets the surrounding plain text around the input, excluding the preedit
++        text.
++
++        The client should notify the compositor of any changes in any of the
++        values carried with this request, including changes caused by handling
++        incoming text-input events as well as changes caused by other
++        mechanisms like keyboard typing.
++
++        If the client is unaware of the text around the cursor, it should not
++        issue this request, to signify lack of support to the compositor.
++
++        Text is UTF-8 encoded, and should include the cursor position, the
++        complete selection and additional characters before and after them.
++        There is a maximum length of wayland messages, so text can not be
++        longer than 4000 bytes.
++
++        Cursor is the byte offset of the cursor within text buffer.
++
++        Anchor is the byte offset of the selection anchor within text buffer.
++        If there is no selected text, anchor is the same as cursor.
++
++        If any preedit text is present, it is replaced with a cursor for the
++        purpose of this event.
++
++        Values set with this request are double-buffered. They will get applied
++        on the next zwp_text_input_v3.commit request, and stay valid until the
++        next committed enable or disable request.
++
++        The initial state for affected fields is empty, meaning that the text
++        input does not support sending surrounding text. If the empty values
++        get applied, subsequent attempts to change them may have no effect.
++      </description>
++      <arg name="text" type="string"/>
++      <arg name="cursor" type="int"/>
++      <arg name="anchor" type="int"/>
++    </request>
++
++    <enum name="change_cause">
++      <description summary="text change reason">
++        Reason for the change of surrounding text or cursor posision.
++      </description>
++      <entry name="input_method" value="0" summary="input method caused the change"/>
++      <entry name="other" value="1" summary="something else than the input method caused the change"/>
++    </enum>
++
++    <request name="set_text_change_cause">
++      <description summary="indicates the cause of surrounding text change">
++        Tells the compositor why the text surrounding the cursor changed.
++
++        Whenever the client detects an external change in text, cursor, or
++        anchor posision, it must issue this request to the compositor. This
++        request is intended to give the input method a chance to update the
++        preedit text in an appropriate way, e.g. by removing it when the user
++        starts typing with a keyboard.
++
++        cause describes the source of the change.
++
++        The value set with this request is double-buffered. It must be applied
++        and reset to initial at the next zwp_text_input_v3.commit request.
++
++        The initial value of cause is input_method.
++      </description>
++      <arg name="cause" type="uint" enum="change_cause"/>
++    </request>
++
++    <enum name="content_hint" bitfield="true">
++      <description summary="content hint">
++        Content hint is a bitmask to allow to modify the behavior of the text
++        input.
++      </description>
++      <entry name="none" value="0x0" summary="no special behavior"/>
++      <entry name="completion" value="0x1" summary="suggest word completions"/>
++      <entry name="spellcheck" value="0x2" summary="suggest word corrections"/>
++      <entry name="auto_capitalization" value="0x4" summary="switch to uppercase letters at the start of a sentence"/>
++      <entry name="lowercase" value="0x8" summary="prefer lowercase letters"/>
++      <entry name="uppercase" value="0x10" summary="prefer uppercase letters"/>
++      <entry name="titlecase" value="0x20" summary="prefer casing for titles and headings (can be language dependent)"/>
++      <entry name="hidden_text" value="0x40" summary="characters should be hidden"/>
++      <entry name="sensitive_data" value="0x80" summary="typed text should not be stored"/>
++      <entry name="latin" value="0x100" summary="just Latin characters should be entered"/>
++      <entry name="multiline" value="0x200" summary="the text input is multiline"/>
++    </enum>
++
++    <enum name="content_purpose">
++      <description summary="content purpose">
++        The content purpose allows to specify the primary purpose of a text
++        input.
++
++        This allows an input method to show special purpose input panels with
++        extra characters or to disallow some characters.
++      </description>
++      <entry name="normal" value="0" summary="default input, allowing all characters"/>
++      <entry name="alpha" value="1" summary="allow only alphabetic characters"/>
++      <entry name="digits" value="2" summary="allow only digits"/>
++      <entry name="number" value="3" summary="input a number (including decimal separator and sign)"/>
++      <entry name="phone" value="4" summary="input a phone number"/>
++      <entry name="url" value="5" summary="input an URL"/>
++      <entry name="email" value="6" summary="input an email address"/>
++      <entry name="name" value="7" summary="input a name of a person"/>
++      <entry name="password" value="8" summary="input a password (combine with sensitive_data hint)"/>
++      <entry name="pin" value="9" summary="input is a numeric password (combine with sensitive_data hint)"/>
++      <entry name="date" value="10" summary="input a date"/>
++      <entry name="time" value="11" summary="input a time"/>
++      <entry name="datetime" value="12" summary="input a date and time"/>
++      <entry name="terminal" value="13" summary="input for a terminal"/>
++    </enum>
++
++    <request name="set_content_type">
++      <description summary="set content purpose and hint">
++        Sets the content purpose and content hint. While the purpose is the
++        basic purpose of an input field, the hint flags allow to modify some of
++        the behavior.
++
++        Values set with this request are double-buffered. They will get applied
++        on the next zwp_text_input_v3.commit request.
++        Subsequent attempts to update them may have no effect. The values
++        remain valid until the next committed enable or disable request.
++
++        The initial value for hint is none, and the initial value for purpose
++        is normal.
++      </description>
++      <arg name="hint" type="uint" enum="content_hint"/>
++      <arg name="purpose" type="uint" enum="content_purpose"/>
++    </request>
++
++    <request name="set_cursor_rectangle">
++      <description summary="set cursor position">
++        Marks an area around the cursor as a x, y, width, height rectangle in
++        surface local coordinates.
++
++        Allows the compositor to put a window with word suggestions near the
++        cursor, without obstructing the text being input.
++
++        If the client is unaware of the position of edited text, it should not
++        issue this request, to signify lack of support to the compositor.
++
++        Values set with this request are double-buffered. They will get applied
++        on the next zwp_text_input_v3.commit request, and stay valid until the
++        next committed enable or disable request.
++
++        The initial values describing a cursor rectangle are empty. That means
++        the text input does not support describing the cursor area. If the
++        empty values get applied, subsequent attempts to change them may have
++        no effect.
++      </description>
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="commit">
++      <description summary="commit state">
++        Atomically applies state changes recently sent to the compositor.
++
++        The commit request establishes and updates the state of the client, and
++        must be issued after any changes to apply them.
++
++        Text input state (enabled status, content purpose, content hint,
++        surrounding text and change cause, cursor rectangle) is conceptually
++        double-buffered within the context of a text input, i.e. between a
++        committed enable request and the following committed enable or disable
++        request.
++
++        Protocol requests modify the pending state, as opposed to the current
++        state in use by the input method. A commit request atomically applies
++        all pending state, replacing the current state. After commit, the new
++        pending state is as documented for each related request.
++
++        Requests are applied in the order of arrival.
++
++        Neither current nor pending state are modified unless noted otherwise.
++
++        The compositor must count the number of commit requests coming from
++        each zwp_text_input_v3 object and use the count as the serial in done
++        events.
++      </description>
++    </request>
++
++    <event name="enter">
++      <description summary="enter event">
++        Notification that this seat's text-input focus is on a certain surface.
++
++        If client has created multiple text input objects, compositor must send
++        this event to all of them.
++
++        When the seat has the keyboard capability the text-input focus follows
++        the keyboard focus. This event sets the current surface for the
++        text-input object.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++        Notification that this seat's text-input focus is no longer on a
++        certain surface. The client should reset any preedit string previously
++        set.
++
++        The leave notification clears the current surface. It is sent before
++        the enter notification for the new focus. After leave event, compositor
++        must ignore requests from any text input instances until next enter
++        event.
++
++        When the seat has the keyboard capability the text-input focus follows
++        the keyboard focus.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </event>
++
++    <event name="preedit_string">
++      <description summary="pre-edit">
++        Notify when a new composing text (pre-edit) should be set at the
++        current cursor position. Any previously set composing text must be
++        removed. Any previously existing selected text must be removed.
++
++        The argument text contains the pre-edit string buffer.
++
++        The parameters cursor_begin and cursor_end are counted in bytes
++        relative to the beginning of the submitted text buffer. Cursor should
++        be hidden when both are equal to -1.
++
++        They could be represented by the client as a line if both values are
++        the same, or as a text highlight otherwise.
++
++        Values set with this event are double-buffered. They must be applied
++        and reset to initial on the next zwp_text_input_v3.done event.
++
++        The initial value of text is an empty string, and cursor_begin,
++        cursor_end and cursor_hidden are all 0.
++      </description>
++      <arg name="text" type="string" allow-null="true"/>
++      <arg name="cursor_begin" type="int"/>
++      <arg name="cursor_end" type="int"/>
++    </event>
++
++    <event name="commit_string">
++      <description summary="text commit">
++        Notify when text should be inserted into the editor widget. The text to
++        commit could be either just a single character after a key press or the
++        result of some composing (pre-edit).
++
++        Values set with this event are double-buffered. They must be applied
++        and reset to initial on the next zwp_text_input_v3.done event.
++
++        The initial value of text is an empty string.
++      </description>
++      <arg name="text" type="string" allow-null="true"/>
++    </event>
++
++    <event name="delete_surrounding_text">
++      <description summary="delete surrounding text">
++        Notify when the text around the current cursor position should be
++        deleted.
++
++        Before_length and after_length are the number of bytes before and after
++        the current cursor index (excluding the selection) to delete.
++
++        If a preedit text is present, in effect before_length is counted from
++        the beginning of it, and after_length from its end (see done event
++        sequence).
++
++        Values set with this event are double-buffered. They must be applied
++        and reset to initial on the next zwp_text_input_v3.done event.
++
++        The initial values of both before_length and after_length are 0.
++      </description>
++      <arg name="before_length" type="uint" summary="length of text before current cursor position"/>
++      <arg name="after_length" type="uint" summary="length of text after current cursor position"/>
++    </event>
++
++    <event name="done">
++      <description summary="apply changes">
++        Instruct the application to apply changes to state requested by the
++        preedit_string, commit_string and delete_surrounding_text events. The
++        state relating to these events is double-buffered, and each one
++        modifies the pending state. This event replaces the current state with
++        the pending state.
++
++        The application must proceed by evaluating the changes in the following
++        order:
++
++        1. Replace existing preedit string with the cursor.
++        2. Delete requested surrounding text.
++        3. Insert commit string with the cursor at its end.
++        4. Calculate surrounding text to send.
++        5. Insert new preedit text in cursor position.
++        6. Place cursor inside preedit text.
++
++        The serial number reflects the last state of the zwp_text_input_v3
++        object known to the compositor. The value of the serial argument must
++        be equal to the number of commit requests already issued on that object.
++
++        When the client receives a done event with a serial different than the
++        number of past commit requests, it must proceed with evaluating and
++        applying the changes as normal, except it should not change the current
++        state of the zwp_text_input_v3 object. All pending state requests
++        (set_surrounding_text, set_content_type and set_cursor_rectangle) on
++        the zwp_text_input_v3 object should be sent and committed after
++        receiving a zwp_text_input_v3.done event with a matching serial.
++      </description>
++      <arg name="serial" type="uint"/>
++    </event>
++  </interface>
++
++  <interface name="zwp_text_input_manager_v3" version="1">
++    <description summary="text input manager">
++      A factory for text-input objects. This object is a global singleton.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="Destroy the wp_text_input_manager">
++        Destroy the wp_text_input_manager object.
++      </description>
++    </request>
++
++    <request name="get_text_input">
++      <description summary="create a new text input object">
++        Creates a new text-input object for a given seat.
++      </description>
++      <arg name="id" type="new_id" interface="zwp_text_input_v3"/>
++      <arg name="seat" type="object" interface="wl_seat"/>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..73f0c520448e261ad3994e6365ca9ad0ca8008d3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++xdg_decoration protocol
++
++Maintainers:
++Simon Ser <contact@emersion.fr>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e5967751d7f3db14859982ef3704fc28e4db7b79
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,156 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_decoration_unstable_v1">
++  <copyright>
++    Copyright © 2018 Simon Ser
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zxdg_decoration_manager_v1" version="1">
++    <description summary="window decoration manager">
++      This interface allows a compositor to announce support for server-side
++      decorations.
++
++      A window decoration is a set of window controls as deemed appropriate by
++      the party managing them, such as user interface components used to move,
++      resize and change a window's state.
++
++      A client can use this protocol to request being decorated by a supporting
++      compositor.
++
++      If compositor and client do not negotiate the use of a server-side
++      decoration using this protocol, clients continue to self-decorate as they
++      see fit.
++
++      Warning! The protocol described in this file is experimental and
++      backward incompatible changes may be made. Backward compatible changes
++      may be added together with the corresponding interface version bump.
++      Backward incompatible changes are done by bumping the version number in
++      the protocol and interface names and resetting the interface version.
++      Once the protocol is to be declared stable, the 'z' prefix and the
++      version number in the protocol and interface names are removed and the
++      interface version number is reset.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the decoration manager object">
++        Destroy the decoration manager. This doesn't destroy objects created
++        with the manager.
++      </description>
++    </request>
++
++    <request name="get_toplevel_decoration">
++      <description summary="create a new toplevel decoration object">
++        Create a new decoration object associated with the given toplevel.
++
++        Creating an xdg_toplevel_decoration from an xdg_toplevel which has a
++        buffer attached or committed is a client error, and any attempts by a
++        client to attach or manipulate a buffer prior to the first
++        xdg_toplevel_decoration.configure event must also be treated as
++        errors.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_toplevel_decoration_v1"/>
++      <arg name="toplevel" type="object" interface="xdg_toplevel"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_toplevel_decoration_v1" version="1">
++    <description summary="decoration object for a toplevel surface">
++      The decoration object allows the compositor to toggle server-side window
++      decorations for a toplevel surface. The client can request to switch to
++      another mode.
++
++      The xdg_toplevel_decoration object must be destroyed before its
++      xdg_toplevel.
++    </description>
++
++    <enum name="error">
++      <entry name="unconfigured_buffer" value="0"
++        summary="xdg_toplevel has a buffer attached before configure"/>
++      <entry name="already_constructed" value="1"
++        summary="xdg_toplevel already has a decoration object"/>
++      <entry name="orphaned" value="2"
++        summary="xdg_toplevel destroyed before the decoration object"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the decoration object">
++        Switch back to a mode without any server-side decorations at the next
++        commit.
++      </description>
++    </request>
++
++    <enum name="mode">
++      <description summary="window decoration modes">
++        These values describe window decoration modes.
++      </description>
++      <entry name="client_side" value="1"
++        summary="no server-side window decoration"/>
++      <entry name="server_side" value="2"
++        summary="server-side window decoration"/>
++    </enum>
++
++    <request name="set_mode">
++      <description summary="set the decoration mode">
++        Set the toplevel surface decoration mode. This informs the compositor
++        that the client prefers the provided decoration mode.
++
++        After requesting a decoration mode, the compositor will respond by
++        emitting an xdg_surface.configure event. The client should then update
++        its content, drawing it without decorations if the received mode is
++        server-side decorations. The client must also acknowledge the configure
++        when committing the new content (see xdg_surface.ack_configure).
++
++        The compositor can decide not to use the client's mode and enforce a
++        different mode instead.
++
++        Clients whose decoration mode depend on the xdg_toplevel state may send
++        a set_mode request in response to an xdg_surface.configure event and wait
++        for the next xdg_surface.configure event to prevent unwanted state.
++        Such clients are responsible for preventing configure loops and must
++        make sure not to send multiple successive set_mode requests with the
++        same decoration mode.
++      </description>
++      <arg name="mode" type="uint" enum="mode" summary="the decoration mode"/>
++    </request>
++
++    <request name="unset_mode">
++      <description summary="unset the decoration mode">
++        Unset the toplevel surface decoration mode. This informs the compositor
++        that the client doesn't prefer a particular decoration mode.
++
++        This request has the same semantics as set_mode.
++      </description>
++    </request>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++        The configure event asks the client to change its decoration mode. The
++        configured state should not be applied immediately. Clients must send an
++        ack_configure in response to this event. See xdg_surface.configure and
++        xdg_surface.ack_configure for details.
++
++        A configure event can be sent at any time. The specified mode must be
++        obeyed by the client.
++      </description>
++      <arg name="mode" type="uint" enum="mode" summary="the decoration mode"/>
++    </event>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f5bcb838f342d3a88ba01adaee65be307d1eec03
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++xdg foreign protocol
++
++Maintainers:
++Jonas Ådahl <jadahl@gmail.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..913963aa524c02a97214393df46f251efbb7f7df
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,182 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_foreign_unstable_v1">
++
++  <copyright>
++    Copyright © 2015-2016 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for exporting xdg surface handles">
++    This protocol specifies a way for making it possible to reference a surface
++    of a different client. With such a reference, a client can, by using the
++    interfaces provided by this protocol, manipulate the relationship between
++    its own surfaces and the surface of some other client. For example, stack
++    some of its own surface above the other clients surface.
++
++    In order for a client A to get a reference of a surface of client B, client
++    B must first export its surface using xdg_exporter.export. Upon doing this,
++    client B will receive a handle (a unique string) that it may share with
++    client A in some way (for example D-Bus). After client A has received the
++    handle from client B, it may use xdg_importer.import to create a reference
++    to the surface client B just exported. See the corresponding requests for
++    details.
++
++    A possible use case for this is out-of-process dialogs. For example when a
++    sandboxed client without file system access needs the user to select a file
++    on the file system, given sandbox environment support, it can export its
++    surface, passing the exported surface handle to an unsandboxed process that
++    can show a file browser dialog and stack it above the sandboxed client's
++    surface.
++
++    Warning! The protocol described in this file is experimental and backward
++    incompatible changes may be made. Backward compatible changes may be added
++    together with the corresponding interface version bump. Backward
++    incompatible changes are done by bumping the version number in the protocol
++    and interface names and resetting the interface version. Once the protocol
++    is to be declared stable, the 'z' prefix and the version number in the
++    protocol and interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zxdg_exporter_v1" version="1">
++    <description summary="interface for exporting surfaces">
++      A global interface used for exporting surfaces that can later be imported
++      using xdg_importer.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_exporter object">
++      Notify the compositor that the xdg_exporter object will no longer be
++      used.
++      </description>
++    </request>
++
++    <request name="export">
++      <description summary="export a surface">
++      The export request exports the passed surface so that it can later be
++      imported via xdg_importer. When called, a new xdg_exported object will
++      be created and xdg_exported.handle will be sent immediately. See the
++      corresponding interface and event for details.
++
++      A surface may be exported multiple times, and each exported handle may
++      be used to create an xdg_imported multiple times. Only xdg_surface
++      surfaces may be exported.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_exported_v1"
++         summary="the new xdg_exported object"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface to export"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_importer_v1" version="1">
++    <description summary="interface for importing surfaces">
++      A global interface used for importing surfaces exported by xdg_exporter.
++      With this interface, a client can create a reference to a surface of
++      another client.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_importer object">
++      Notify the compositor that the xdg_importer object will no longer be
++      used.
++      </description>
++    </request>
++
++    <request name="import">
++      <description summary="import a surface">
++      The import request imports a surface from any client given a handle
++      retrieved by exporting said surface using xdg_exporter.export. When
++      called, a new xdg_imported object will be created. This new object
++      represents the imported surface, and the importing client can
++      manipulate its relationship using it. See xdg_imported for details.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_imported_v1"
++         summary="the new xdg_imported object"/>
++      <arg name="handle" type="string"
++         summary="the exported surface handle"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_exported_v1" version="1">
++    <description summary="an exported surface handle">
++      An xdg_exported object represents an exported reference to a surface. The
++      exported surface may be referenced as long as the xdg_exported object not
++      destroyed. Destroying the xdg_exported invalidates any relationship the
++      importer may have established using xdg_imported.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unexport the exported surface">
++      Revoke the previously exported surface. This invalidates any
++      relationship the importer may have set up using the xdg_imported created
++      given the handle sent via xdg_exported.handle.
++      </description>
++    </request>
++
++    <event name="handle">
++      <description summary="the exported surface handle">
++      The handle event contains the unique handle of this exported surface
++      reference. It may be shared with any client, which then can use it to
++      import the surface by calling xdg_importer.import. A handle may be
++      used to import the surface multiple times.
++      </description>
++      <arg name="handle" type="string" summary="the exported surface handle"/>
++    </event>
++  </interface>
++
++  <interface name="zxdg_imported_v1" version="1">
++    <description summary="an imported surface handle">
++      An xdg_imported object represents an imported reference to surface exported
++      by some client. A client can use this interface to manipulate
++      relationships between its own surfaces and the imported surface.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_imported object">
++      Notify the compositor that it will no longer use the xdg_imported
++      object. Any relationship that may have been set up will at this point
++      be invalidated.
++      </description>
++    </request>
++
++    <request name="set_parent_of">
++      <description summary="set as the parent of some surface">
++      Set the imported surface as the parent of some surface of the client.
++      The passed surface must be a toplevel xdg_surface. Calling this function
++      sets up a surface to surface relation with the same stacking and positioning
++      semantics as xdg_surface.set_parent.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the child surface"/>
++    </request>
++
++    <event name="destroyed">
++      <description summary="the imported surface handle has been destroyed">
++      The imported surface handle has been destroyed and any relationship set
++      up has been invalidated. This may happen for various reasons, for
++      example if the exported surface or the exported surface handle has been
++      destroyed, if the handle used for importing was invalid.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cc3271dca4d6211bf6d04c34c0ca973c52f9b552
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,200 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_foreign_unstable_v2">
++
++  <copyright>
++    Copyright © 2015-2016 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for exporting xdg surface handles">
++    This protocol specifies a way for making it possible to reference a surface
++    of a different client. With such a reference, a client can, by using the
++    interfaces provided by this protocol, manipulate the relationship between
++    its own surfaces and the surface of some other client. For example, stack
++    some of its own surface above the other clients surface.
++
++    In order for a client A to get a reference of a surface of client B, client
++    B must first export its surface using xdg_exporter.export_toplevel. Upon
++    doing this, client B will receive a handle (a unique string) that it may
++    share with client A in some way (for example D-Bus). After client A has
++    received the handle from client B, it may use xdg_importer.import_toplevel
++    to create a reference to the surface client B just exported. See the
++    corresponding requests for details.
++
++    A possible use case for this is out-of-process dialogs. For example when a
++    sandboxed client without file system access needs the user to select a file
++    on the file system, given sandbox environment support, it can export its
++    surface, passing the exported surface handle to an unsandboxed process that
++    can show a file browser dialog and stack it above the sandboxed client's
++    surface.
++
++    Warning! The protocol described in this file is experimental and backward
++    incompatible changes may be made. Backward compatible changes may be added
++    together with the corresponding interface version bump. Backward
++    incompatible changes are done by bumping the version number in the protocol
++    and interface names and resetting the interface version. Once the protocol
++    is to be declared stable, the 'z' prefix and the version number in the
++    protocol and interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zxdg_exporter_v2" version="1">
++    <description summary="interface for exporting surfaces">
++      A global interface used for exporting surfaces that can later be imported
++      using xdg_importer.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_exporter object">
++      Notify the compositor that the xdg_exporter object will no longer be
++      used.
++      </description>
++    </request>
++
++    <enum name="error">
++      <description summary="error values">
++        These errors can be emitted in response to invalid xdg_exporter
++        requests.
++      </description>
++      <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/>
++    </enum>
++
++    <request name="export_toplevel">
++      <description summary="export a toplevel surface">
++      The export_toplevel request exports the passed surface so that it can later be
++      imported via xdg_importer. When called, a new xdg_exported object will
++      be created and xdg_exported.handle will be sent immediately. See the
++      corresponding interface and event for details.
++
++      A surface may be exported multiple times, and each exported handle may
++      be used to create an xdg_imported multiple times. Only xdg_toplevel
++        equivalent surfaces may be exported, otherwise an invalid_surface
++        protocol error is sent.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_exported_v2"
++         summary="the new xdg_exported object"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface to export"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_importer_v2" version="1">
++    <description summary="interface for importing surfaces">
++      A global interface used for importing surfaces exported by xdg_exporter.
++      With this interface, a client can create a reference to a surface of
++      another client.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_importer object">
++      Notify the compositor that the xdg_importer object will no longer be
++      used.
++      </description>
++    </request>
++
++    <request name="import_toplevel">
++      <description summary="import a toplevel surface">
++      The import_toplevel request imports a surface from any client given a handle
++      retrieved by exporting said surface using xdg_exporter.export_toplevel.
++      When called, a new xdg_imported object will be created. This new object
++      represents the imported surface, and the importing client can
++      manipulate its relationship using it. See xdg_imported for details.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_imported_v2"
++         summary="the new xdg_imported object"/>
++      <arg name="handle" type="string"
++         summary="the exported surface handle"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_exported_v2" version="1">
++    <description summary="an exported surface handle">
++      An xdg_exported object represents an exported reference to a surface. The
++      exported surface may be referenced as long as the xdg_exported object not
++      destroyed. Destroying the xdg_exported invalidates any relationship the
++      importer may have established using xdg_imported.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unexport the exported surface">
++      Revoke the previously exported surface. This invalidates any
++      relationship the importer may have set up using the xdg_imported created
++      given the handle sent via xdg_exported.handle.
++      </description>
++    </request>
++
++    <event name="handle">
++      <description summary="the exported surface handle">
++      The handle event contains the unique handle of this exported surface
++      reference. It may be shared with any client, which then can use it to
++      import the surface by calling xdg_importer.import_toplevel. A handle
++      may be used to import the surface multiple times.
++      </description>
++      <arg name="handle" type="string" summary="the exported surface handle"/>
++    </event>
++  </interface>
++
++  <interface name="zxdg_imported_v2" version="1">
++    <description summary="an imported surface handle">
++      An xdg_imported object represents an imported reference to surface exported
++      by some client. A client can use this interface to manipulate
++      relationships between its own surfaces and the imported surface.
++    </description>
++
++    <enum name="error">
++      <description summary="error values">
++        These errors can be emitted in response to invalid xdg_imported
++        requests.
++      </description>
++      <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_imported object">
++      Notify the compositor that it will no longer use the xdg_imported
++      object. Any relationship that may have been set up will at this point
++      be invalidated.
++      </description>
++    </request>
++
++    <request name="set_parent_of">
++      <description summary="set as the parent of some surface">
++        Set the imported surface as the parent of some surface of the client.
++        The passed surface must be an xdg_toplevel equivalent, otherwise an
++        invalid_surface protocol error is sent. Calling this function sets up
++        a surface to surface relation with the same stacking and positioning
++        semantics as xdg_toplevel.set_parent.
++      </description>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the child surface"/>
++    </request>
++
++    <event name="destroyed">
++      <description summary="the imported surface handle has been destroyed">
++      The imported surface handle has been destroyed and any relationship set
++      up has been invalidated. This may happen for various reasons, for
++      example if the exported surface or the exported surface handle has been
++      destroyed, if the handle used for importing was invalid.
++      </description>
++    </event>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e42b7115fd8e6ae3e781401712e91c1fd5f2a645
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++xdg_output protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9a5b7900097cc2fe92dc0fb6d20b5e5395a11a70
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,220 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_output_unstable_v1">
++
++  <copyright>
++    Copyright © 2017 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol to describe output regions">
++    This protocol aims at describing outputs in a way which is more in line
++    with the concept of an output on desktop oriented systems.
++
++    Some information are more specific to the concept of an output for
++    a desktop oriented system and may not make sense in other applications,
++    such as IVI systems for example.
++
++    Typically, the global compositor space on a desktop system is made of
++    a contiguous or overlapping set of rectangular regions.
++
++    Some of the information provided in this protocol might be identical
++    to their counterparts already available from wl_output, in which case
++    the information provided by this protocol should be preferred to their
++    equivalent in wl_output. The goal is to move the desktop specific
++    concepts (such as output location within the global compositor space,
++    the connector name and types, etc.) out of the core wl_output protocol.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible
++    changes may be added together with the corresponding interface
++    version bump.
++    Backward incompatible changes are done by bumping the version
++    number in the protocol and interface names and resetting the
++    interface version. Once the protocol is to be declared stable,
++    the 'z' prefix and the version number in the protocol and
++    interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zxdg_output_manager_v1" version="3">
++    <description summary="manage xdg_output objects">
++      A global factory interface for xdg_output objects.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_output_manager object">
++      Using this request a client can tell the server that it is not
++      going to use the xdg_output_manager object anymore.
++
++      Any objects already created through this instance are not affected.
++      </description>
++    </request>
++
++    <request name="get_xdg_output">
++      <description summary="create an xdg output from a wl_output">
++      This creates a new xdg_output object for the given wl_output.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_output_v1"/>
++      <arg name="output" type="object" interface="wl_output"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_output_v1" version="3">
++    <description summary="compositor logical output region">
++      An xdg_output describes part of the compositor geometry.
++
++      This typically corresponds to a monitor that displays part of the
++      compositor space.
++
++      For objects version 3 onwards, after all xdg_output properties have been
++      sent (when the object is created and when properties are updated), a
++      wl_output.done event is sent. This allows changes to the output
++      properties to be seen as atomic, even if they happen via multiple events.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_output object">
++      Using this request a client can tell the server that it is not
++      going to use the xdg_output object anymore.
++      </description>
++    </request>
++
++    <event name="logical_position">
++      <description summary="position of the output within the global compositor space">
++      The position event describes the location of the wl_output within
++      the global compositor space.
++
++      The logical_position event is sent after creating an xdg_output
++      (see xdg_output_manager.get_xdg_output) and whenever the location
++      of the output changes within the global compositor space.
++      </description>
++      <arg name="x" type="int"
++         summary="x position within the global compositor space"/>
++      <arg name="y" type="int"
++         summary="y position within the global compositor space"/>
++    </event>
++
++    <event name="logical_size">
++      <description summary="size of the output in the global compositor space">
++      The logical_size event describes the size of the output in the
++      global compositor space.
++
++      For example, a surface without any buffer scale, transformation
++      nor rotation set, with the size matching the logical_size will
++      have the same size as the corresponding output when displayed.
++
++      Most regular Wayland clients should not pay attention to the
++      logical size and would rather rely on xdg_shell interfaces.
++
++      Some clients such as Xwayland, however, need this to configure
++      their surfaces in the global compositor space as the compositor
++      may apply a different scale from what is advertised by the output
++      scaling property (to achieve fractional scaling, for example).
++
++      For example, for a wl_output mode 3840×2160 and a scale factor 2:
++
++      - A compositor not scaling the surface buffers will advertise a
++        logical size of 3840×2160,
++
++      - A compositor automatically scaling the surface buffers will
++        advertise a logical size of 1920×1080,
++
++      - A compositor using a fractional scale of 1.5 will advertise a
++        logical size of 2560×1440.
++
++      For example, for a wl_output mode 1920×1080 and a 90 degree rotation,
++      the compositor will advertise a logical size of 1080x1920.
++
++      The logical_size event is sent after creating an xdg_output
++      (see xdg_output_manager.get_xdg_output) and whenever the logical
++      size of the output changes, either as a result of a change in the
++      applied scale or because of a change in the corresponding output
++      mode(see wl_output.mode) or transform (see wl_output.transform).
++      </description>
++      <arg name="width" type="int"
++         summary="width in global compositor space"/>
++      <arg name="height" type="int"
++         summary="height in global compositor space"/>
++    </event>
++
++    <event name="done">
++      <description summary="all information about the output have been sent">
++      This event is sent after all other properties of an xdg_output
++      have been sent.
++
++      This allows changes to the xdg_output properties to be seen as
++      atomic, even if they happen via multiple events.
++
++      For objects version 3 onwards, this event is deprecated. Compositors
++      are not required to send it anymore and must send wl_output.done
++      instead.
++      </description>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <event name="name" since="2">
++      <description summary="name of this output">
++      Many compositors will assign names to their outputs, show them to the
++      user, allow them to be configured by name, etc. The client may wish to
++      know this name as well to offer the user similar behaviors.
++
++      The naming convention is compositor defined, but limited to
++      alphanumeric characters and dashes (-). Each name is unique among all
++      wl_output globals, but if a wl_output global is destroyed the same name
++      may be reused later. The names will also remain consistent across
++      sessions with the same hardware and software configuration.
++
++      Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
++      not assume that the name is a reflection of an underlying DRM
++      connector, X11 connection, etc.
++
++      The name event is sent after creating an xdg_output (see
++      xdg_output_manager.get_xdg_output). This event is only sent once per
++      xdg_output, and the name does not change over the lifetime of the
++      wl_output global.
++      </description>
++      <arg name="name" type="string" summary="output name"/>
++    </event>
++
++    <event name="description" since="2">
++      <description summary="human-readable description of this output">
++      Many compositors can produce human-readable descriptions of their
++      outputs.  The client may wish to know this description as well, to
++      communicate the user for various purposes.
++
++      The description is a UTF-8 string with no convention defined for its
++      contents. Examples might include 'Foocorp 11" Display' or 'Virtual X11
++      output via :1'.
++
++      The description event is sent after creating an xdg_output (see
++      xdg_output_manager.get_xdg_output) and whenever the description
++      changes. The description is optional, and may not be sent at all.
++
++      For objects of version 2 and lower, this event is only sent once per
++      xdg_output, and the description does not change over the lifetime of
++      the wl_output global.
++      </description>
++      <arg name="description" type="string" summary="output description"/>
++    </event>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..96ae4ef007301bbbdbd06353b35c6ba9460cdd11
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++xdg shell protocol
++
++Maintainers:
++Jasper St. Pierre <jstpierre@mecheye.net>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ef0180d0107b6e9e548fe5904d3beb1d2dac41e0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,623 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell_unstable_v5">
++
++  <copyright>
++    Copyright © 2008-2013 Kristian Høgsberg
++    Copyright © 2013      Rafael Antognolli
++    Copyright © 2013      Jasper St. Pierre
++    Copyright © 2010-2013 Intel Corporation
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="xdg_shell" version="1">
++    <description summary="create desktop-style surfaces">
++      xdg_shell allows clients to turn a wl_surface into a "real window"
++      which can be dragged, resized, stacked, and moved around by the
++      user. Everything about this interface is suited towards traditional
++      desktop environments.
++    </description>
++
++    <enum name="version">
++      <description summary="latest protocol version">
++      The 'current' member of this enum gives the version of the
++      protocol.  Implementations can compare this to the version
++      they implement using static_assert to ensure the protocol and
++      implementation versions match.
++      </description>
++      <entry name="current" value="5" summary="Always the latest version"/>
++    </enum>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++      <entry name="defunct_surfaces" value="1" summary="xdg_shell was destroyed before children"/>
++      <entry name="not_the_topmost_popup" value="2" summary="the client tried to map or destroy a non-topmost popup"/>
++      <entry name="invalid_popup_parent" value="3" summary="the client specified an invalid popup parent surface"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy xdg_shell">
++        Destroy this xdg_shell object.
++
++        Destroying a bound xdg_shell object while there are surfaces
++        still alive created by this xdg_shell object instance is illegal
++        and will result in a protocol error.
++      </description>
++    </request>
++
++    <request name="use_unstable_version">
++      <description summary="enable use of this unstable version">
++      Negotiate the unstable version of the interface.  This
++      mechanism is in place to ensure client and server agree on the
++      unstable versions of the protocol that they speak or exit
++      cleanly if they don't agree.  This request will go away once
++      the xdg-shell protocol is stable.
++      </description>
++      <arg name="version" type="int"/>
++    </request>
++
++    <request name="get_xdg_surface">
++      <description summary="create a shell surface from a surface">
++      This creates an xdg_surface for the given surface and gives it the
++      xdg_surface role. A wl_surface can only be given an xdg_surface role
++      once. If get_xdg_surface is called with a wl_surface that already has
++      an active xdg_surface associated with it, or if it had any other role,
++      an error is raised.
++
++      See the documentation of xdg_surface for more details about what an
++      xdg_surface is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_surface"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++
++    <request name="get_xdg_popup">
++      <description summary="create a popup for a surface">
++      This creates an xdg_popup for the given surface and gives it the
++      xdg_popup role. A wl_surface can only be given an xdg_popup role
++      once. If get_xdg_popup is called with a wl_surface that already has
++      an active xdg_popup associated with it, or if it had any other role,
++      an error is raised.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event.
++
++      See the documentation of xdg_popup for more details about what an
++      xdg_popup is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="xdg_popup"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++      <arg name="parent" type="object" interface="wl_surface"/>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++    </request>
++
++    <event name="ping">
++      <description summary="check if the client is alive">
++        The ping event asks the client if it's still alive. Pass the
++        serial specified in the event back to the compositor by sending
++        a "pong" request back with the specified serial.
++
++        Compositors can use this to determine if the client is still
++        alive. It's unspecified what will happen if the client doesn't
++        respond to the ping request, or in what timeframe. Clients should
++        try to respond in a reasonable amount of time.
++
++        A compositor is free to ping in any way it wants, but a client must
++        always respond to any xdg_shell object it created.
++      </description>
++      <arg name="serial" type="uint" summary="pass this to the pong request"/>
++    </event>
++
++    <request name="pong">
++      <description summary="respond to a ping event">
++      A client must respond to a ping event with a pong request or
++      the client may be deemed unresponsive.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the ping event"/>
++    </request>
++  </interface>
++
++  <interface name="xdg_surface" version="1">
++    <description summary="A desktop window">
++      An interface that may be implemented by a wl_surface, for
++      implementations that provide a desktop-style user interface.
++
++      It provides requests to treat surfaces like windows, allowing to set
++      properties like maximized, fullscreen, minimized, and to move and resize
++      them, and associate metadata like title and app id.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_surface state to take effect. Prior to committing the new
++      state, it can set up initial configuration, such as maximizing or setting
++      a window geometry.
++
++      Even without attaching a buffer the compositor must respond to initial
++      committed configuration, for instance sending a configure event with
++      expected window geometry if the client maximized its surface during
++      initialization.
++
++      For a surface to be mapped by the compositor the client must have
++      committed both an xdg_surface state and a buffer.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="Destroy the xdg_surface">
++      Unmap and destroy the window. The window will be effectively
++      hidden from the user's point of view, and all state like
++      maximization, fullscreen, and so on, will be lost.
++      </description>
++    </request>
++
++    <request name="set_parent">
++      <description summary="set the parent of this surface">
++      Set the "parent" of this surface. This window should be stacked
++      above a parent. The parent surface must be mapped as long as this
++      surface is mapped.
++
++      Parent windows should be set on dialogs, toolboxes, or other
++      "auxiliary" surfaces, so that the parent is raised when the dialog
++      is raised.
++      </description>
++      <arg name="parent" type="object" interface="xdg_surface" allow-null="true"/>
++    </request>
++
++    <request name="set_title">
++      <description summary="set surface title">
++      Set a short title for the surface.
++
++      This string may be used to identify the surface in a task bar,
++      window list, or other user interface elements provided by the
++      compositor.
++
++      The string must be encoded in UTF-8.
++      </description>
++      <arg name="title" type="string"/>
++    </request>
++
++    <request name="set_app_id">
++      <description summary="set application ID">
++      Set an application identifier for the surface.
++
++      The app ID identifies the general class of applications to which
++      the surface belongs. The compositor can use this to group multiple
++      surfaces together, or to determine how to launch a new application.
++
++      For D-Bus activatable applications, the app ID is used as the D-Bus
++      service name.
++
++      The compositor shell will try to group application surfaces together
++      by their app ID.  As a best practice, it is suggested to select app
++      ID's that match the basename of the application's .desktop file.
++      For example, "org.freedesktop.FooViewer" where the .desktop file is
++      "org.freedesktop.FooViewer.desktop".
++
++      See the desktop-entry specification [0] for more details on
++      application identifiers and how they relate to well-known D-Bus
++      names and .desktop files.
++
++      [0] http://standards.freedesktop.org/desktop-entry-spec/
++      </description>
++      <arg name="app_id" type="string"/>
++    </request>
++
++    <request name="show_window_menu">
++      <description summary="show the window menu">
++        Clients implementing client-side decorations might want to show
++        a context menu when right-clicking on the decorations, giving the
++        user a menu that they can use to maximize or minimize the window.
++
++        This request asks the compositor to pop up such a window menu at
++        the given position, relative to the local surface coordinates of
++        the parent surface. There are no guarantees as to what menu items
++        the window menu contains.
++
++        This request must be used in response to some sort of user action
++        like a button press, key press, or touch down event.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++      <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++    </request>
++
++    <request name="move">
++      <description summary="start an interactive move">
++      Start an interactive, user-driven move of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive move (touch,
++      pointer, etc).
++
++      The server may ignore move requests depending on the state of
++      the surface (e.g. fullscreen or maximized), or if the passed serial
++      is no longer valid.
++
++      If triggered, the surface will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the move. It is up to the
++      compositor to visually indicate that the move is taking place, such as
++      updating a pointer cursor, during the move. There is no guarantee
++      that the device focus will return when the move is completed.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++    </request>
++
++    <enum name="resize_edge">
++      <description summary="edge values for resizing">
++      These values are used to indicate which edge of a surface
++      is being dragged in a resize operation.
++      </description>
++      <entry name="none" value="0"/>
++      <entry name="top" value="1"/>
++      <entry name="bottom" value="2"/>
++      <entry name="left" value="4"/>
++      <entry name="top_left" value="5"/>
++      <entry name="bottom_left" value="6"/>
++      <entry name="right" value="8"/>
++      <entry name="top_right" value="9"/>
++      <entry name="bottom_right" value="10"/>
++    </enum>
++
++    <request name="resize">
++      <description summary="start an interactive resize">
++      Start a user-driven, interactive resize of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive resize (touch,
++      pointer, etc).
++
++      The server may ignore resize requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++
++      If triggered, the client will receive configure events with the
++      "resize" state enum value and the expected sizes. See the "resize"
++      enum value for more details about what is required. The client
++      must also acknowledge configure events using "ack_configure". After
++      the resize is completed, the client will receive another "configure"
++      event without the resize state.
++
++      If triggered, the surface also will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++      compositor to visually indicate that the resize is taking place,
++      such as updating a pointer cursor, during the resize. There is no
++      guarantee that the device focus will return when the resize is
++      completed.
++
++      The edges parameter specifies how the surface should be resized,
++      and is one of the values of the resize_edge enum. The compositor
++      may use this information to update the surface position for
++      example when dragging the top left corner. The compositor may also
++      use this information to adapt its behavior, e.g. choose an
++      appropriate cursor image.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
++    </request>
++
++    <enum name="state">
++      <description summary="types of state on the surface">
++        The different state values used on the surface. This is designed for
++        state values like maximized, fullscreen. It is paired with the
++        configure event to ensure that both the client and the compositor
++        setting the state can be synchronized.
++
++        States set in this way are double-buffered. They will get applied on
++        the next commit.
++
++        Desktop environments may extend this enum by taking up a range of
++        values and documenting the range they chose in this description.
++        They are not required to document the values for the range that they
++        chose. Ideally, any good extensions from a desktop environment should
++        make its way into standardization into this enum.
++
++        The current reserved ranges are:
++
++        0x0000 - 0x0FFF: xdg-shell core values, documented below.
++        0x1000 - 0x1FFF: GNOME
++        0x2000 - 0x2FFF: EFL
++      </description>
++      <entry name="maximized" value="1" summary="the surface is maximized">
++      <description summary="the surface is maximized">
++        The surface is maximized. The window geometry specified in the configure
++        event must be obeyed by the client.
++      </description>
++      </entry>
++      <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++      <description summary="the surface is fullscreen">
++        The surface is fullscreen. The window geometry specified in the configure
++        event must be obeyed by the client.
++      </description>
++      </entry>
++      <entry name="resizing" value="3" summary="the surface is being resized">
++      <description summary="the surface is being resized">
++        The surface is being resized. The window geometry specified in the
++        configure event is a maximum; the client cannot resize beyond it.
++        Clients that have aspect ratio or cell sizing configuration can use
++        a smaller size, however.
++      </description>
++      </entry>
++      <entry name="activated" value="4" summary="the surface is now activated">
++      <description summary="the surface is now activated">
++        Client window decorations should be painted as if the window is
++        active. Do not assume this means that the window actually has
++        keyboard or pointer focus.
++      </description>
++      </entry>
++    </enum>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++      The configure event asks the client to resize its surface or to
++      change its state.
++
++      The width and height arguments specify a hint to the window
++      about how its surface should be resized in window geometry
++      coordinates. See set_window_geometry.
++
++      If the width or height arguments are zero, it means the client
++      should decide its own window dimension. This may happen when the
++      compositor need to configure the state of the surface but doesn't
++      have any information about any previous or expected dimension.
++
++      The states listed in the event specify how the width/height
++      arguments should be interpreted, and possibly how it should be
++      drawn.
++
++      Clients should arrange their surface for the new size and
++      states, and then send a ack_configure request with the serial
++      sent in this configure event at some point before committing
++      the new surface.
++
++      If the client receives multiple configure events before it
++        can respond to one, it is free to discard all but the last
++        event it received.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++      <arg name="states" type="array"/>
++      <arg name="serial" type="uint"/>
++    </event>
++
++    <request name="ack_configure">
++      <description summary="ack a configure event">
++        When a configure event is received, if a client commits the
++        surface in response to the configure event, then the client
++        must make an ack_configure request sometime before the commit
++        request, passing along the serial of the configure event.
++
++        For instance, the compositor might use this information to move
++        a surface to the top left only when the client has drawn itself
++        for the maximized or fullscreen state.
++
++        If the client receives multiple configure events before it
++        can respond to one, it only has to ack the last configure event.
++
++        A client is not required to commit immediately after sending
++        an ack_configure request - it may even ack_configure several times
++        before its next surface commit.
++
++        The compositor expects that the most recently received
++        ack_configure request at the time of a commit indicates which
++        configure event the client is responding to.
++      </description>
++      <arg name="serial" type="uint" summary="the serial from the configure event"/>
++    </request>
++
++    <request name="set_window_geometry">
++      <description summary="set the new window geometry">
++        The window geometry of a window is its "visible bounds" from the
++        user's perspective. Client-side decorations often have invisible
++        portions like drop-shadows which should be ignored for the
++        purposes of aligning, placing and constraining windows.
++
++        The window geometry is double buffered, and will be applied at the
++        time wl_surface.commit of the corresponding wl_surface is called.
++
++        Once the window geometry of the surface is set once, it is not
++        possible to unset it, and it will remain the same until
++        set_window_geometry is called again, even if a new subsurface or
++        buffer is attached.
++
++        If never set, the value is the full bounds of the surface,
++        including any subsurfaces. This updates dynamically on every
++        commit. This unset mode is meant for extremely simple clients.
++
++        If responding to a configure event, the window geometry in here
++        must respect the sizing negotiations specified by the states in
++        the configure event.
++
++        The arguments are given in the surface local coordinate space of
++        the wl_surface associated with this xdg_surface.
++
++        The width and height must be greater than zero.
++      </description>
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_maximized">
++      <description summary="maximize the window">
++        Maximize the surface.
++
++        After requesting that the surface should be maximized, the compositor
++        will respond by emitting a configure event with the "maximized" state
++        and the required window geometry. The client should then update its
++        content, drawing it in a maximized state, i.e. without shadow or other
++        decoration outside of the window geometry. The client must also
++        acknowledge the configure when committing the new content (see
++        ack_configure).
++
++        It is up to the compositor to decide how and where to maximize the
++        surface, for example which output and what region of the screen should
++        be used.
++
++        If the surface was already maximized, the compositor will still emit
++        a configure event with the "maximized" state.
++      </description>
++    </request>
++
++    <request name="unset_maximized">
++      <description summary="unmaximize the window">
++        Unmaximize the surface.
++
++        After requesting that the surface should be unmaximized, the compositor
++        will respond by emitting a configure event without the "maximized"
++        state. If available, the compositor will include the window geometry
++        dimensions the window had prior to being maximized in the configure
++        request. The client must then update its content, drawing it in a
++        regular state, i.e. potentially with shadow, etc. The client must also
++        acknowledge the configure when committing the new content (see
++        ack_configure).
++
++        It is up to the compositor to position the surface after it was
++        unmaximized; usually the position the surface had before maximizing, if
++        applicable.
++
++        If the surface was already not maximized, the compositor will still
++        emit a configure event without the "maximized" state.
++      </description>
++    </request>
++
++    <request name="set_fullscreen">
++      <description summary="set the window as fullscreen on a monitor">
++      Make the surface fullscreen.
++
++        You can specify an output that you would prefer to be fullscreen.
++      If this value is NULL, it's up to the compositor to choose which
++        display will be used to map this surface.
++
++        If the surface doesn't cover the whole output, the compositor will
++        position the surface in the center of the output and compensate with
++        black borders filling the rest of the output.
++      </description>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++    </request>
++    <request name="unset_fullscreen" />
++
++    <request name="set_minimized">
++      <description summary="set the window as minimized">
++      Request that the compositor minimize your surface. There is no
++      way to know if the surface is currently minimized, nor is there
++      any way to unset minimization on this surface.
++
++      If you are looking to throttle redrawing when minimized, please
++      instead use the wl_surface.frame event for this, as this will
++      also work with live previews on windows in Alt-Tab, Expose or
++      similar compositor features.
++      </description>
++    </request>
++
++    <event name="close">
++      <description summary="surface wants to be closed">
++        The close event is sent by the compositor when the user
++        wants the surface to be closed. This should be equivalent to
++        the user clicking the close button in client-side decorations,
++        if your application has any...
++
++        This is only a request that the user intends to close your
++        window. The client may choose to ignore this request, or show
++        a dialog to ask the user to save their data...
++      </description>
++    </event>
++  </interface>
++
++  <interface name="xdg_popup" version="1">
++    <description summary="short-lived, popup surfaces for menus">
++      A popup surface is a short-lived, temporary surface that can be
++      used to implement menus. It takes an explicit grab on the surface
++      that will be dismissed when the user dismisses the popup. This can
++      be done by the user clicking outside the surface, using the keyboard,
++      or even locking the screen through closing the lid or a timeout.
++
++      When the popup is dismissed, a popup_done event will be sent out,
++      and at the same time the surface will be unmapped. The xdg_popup
++      object is now inert and cannot be reactivated, so clients should
++      destroy it. Explicitly destroying the xdg_popup object will also
++      dismiss the popup and unmap the surface.
++
++      Clients will receive events for all their surfaces during this
++      grab (which is an "owner-events" grab in X11 parlance). This is
++      done so that users can navigate through submenus and other
++      "nested" popup windows without having to dismiss the topmost
++      popup.
++
++      Clients that want to dismiss the popup when another surface of
++      their own is clicked should dismiss the popup using the destroy
++      request.
++
++      The parent surface must have either an xdg_surface or xdg_popup
++      role.
++
++      Specifying an xdg_popup for the parent means that the popups are
++      nested, with this popup now being the topmost popup. Nested
++      popups must be destroyed in the reverse order they were created
++      in, e.g. the only popup you are allowed to destroy at all times
++      is the topmost one.
++
++      If there is an existing popup when creating a new popup, the
++      parent must be the current topmost popup.
++
++      A parent surface must be mapped before the new popup is mapped.
++
++      When compositors choose to dismiss a popup, they will likely
++      dismiss every nested popup as well. When a compositor dismisses
++      popups, it will follow the same dismissing order as required
++      from the client.
++
++      The x and y arguments passed when creating the popup object specify
++      where the top left of the popup should be placed, relative to the
++      local surface coordinates of the parent surface. See
++      xdg_shell.get_xdg_popup.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_popup state to take effect.
++
++      For a surface to be mapped by the compositor the client must have
++      committed both the xdg_popup state and a buffer.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove xdg_popup interface">
++      This destroys the popup. Explicitly destroying the xdg_popup
++      object will also dismiss the popup, and unmap the surface.
++
++      If this xdg_popup is not the "topmost" popup, a protocol error
++      will be sent.
++      </description>
++    </request>
++
++    <event name="popup_done">
++      <description summary="popup interaction is done">
++      The popup_done event is sent out when a popup is dismissed by the
++      compositor. The client should destroy the xdg_popup object at this
++      point.
++      </description>
++    </event>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5e25e668e8a594582e184e4f67260f72cea8f3b0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1044 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xdg_shell_unstable_v6">
++
++  <copyright>
++    Copyright © 2008-2013 Kristian Høgsberg
++    Copyright © 2013      Rafael Antognolli
++    Copyright © 2013      Jasper St. Pierre
++    Copyright © 2010-2013 Intel Corporation
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <interface name="zxdg_shell_v6" version="1">
++    <description summary="create desktop-style surfaces">
++      xdg_shell allows clients to turn a wl_surface into a "real window"
++      which can be dragged, resized, stacked, and moved around by the
++      user. Everything about this interface is suited towards traditional
++      desktop environments.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++      <entry name="defunct_surfaces" value="1"
++           summary="xdg_shell was destroyed before children"/>
++      <entry name="not_the_topmost_popup" value="2"
++           summary="the client tried to map or destroy a non-topmost popup"/>
++      <entry name="invalid_popup_parent" value="3"
++           summary="the client specified an invalid popup parent surface"/>
++      <entry name="invalid_surface_state" value="4"
++           summary="the client provided an invalid surface state"/>
++      <entry name="invalid_positioner" value="5"
++           summary="the client provided an invalid positioner"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy xdg_shell">
++      Destroy this xdg_shell object.
++
++      Destroying a bound xdg_shell object while there are surfaces
++      still alive created by this xdg_shell object instance is illegal
++      and will result in a protocol error.
++      </description>
++    </request>
++
++    <request name="create_positioner">
++      <description summary="create a positioner object">
++      Create a positioner object. A positioner object is used to position
++      surfaces relative to some parent surface. See the interface description
++      and xdg_surface.get_popup for details.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_positioner_v6"/>
++    </request>
++
++    <request name="get_xdg_surface">
++      <description summary="create a shell surface from a surface">
++      This creates an xdg_surface for the given surface. While xdg_surface
++      itself is not a role, the corresponding surface may only be assigned
++      a role extending xdg_surface, such as xdg_toplevel or xdg_popup.
++
++      This creates an xdg_surface for the given surface. An xdg_surface is
++      used as basis to define a role to a given surface, such as xdg_toplevel
++      or xdg_popup. It also manages functionality shared between xdg_surface
++      based surface roles.
++
++      See the documentation of xdg_surface for more details about what an
++      xdg_surface is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_surface_v6"/>
++      <arg name="surface" type="object" interface="wl_surface"/>
++    </request>
++
++    <request name="pong">
++      <description summary="respond to a ping event">
++      A client must respond to a ping event with a pong request or
++      the client may be deemed unresponsive. See xdg_shell.ping.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the ping event"/>
++    </request>
++
++    <event name="ping">
++      <description summary="check if the client is alive">
++      The ping event asks the client if it's still alive. Pass the
++      serial specified in the event back to the compositor by sending
++      a "pong" request back with the specified serial. See xdg_shell.ping.
++
++      Compositors can use this to determine if the client is still
++      alive. It's unspecified what will happen if the client doesn't
++      respond to the ping request, or in what timeframe. Clients should
++      try to respond in a reasonable amount of time.
++
++      A compositor is free to ping in any way it wants, but a client must
++      always respond to any xdg_shell object it created.
++      </description>
++      <arg name="serial" type="uint" summary="pass this to the pong request"/>
++    </event>
++  </interface>
++
++  <interface name="zxdg_positioner_v6" version="1">
++    <description summary="child surface positioner">
++      The xdg_positioner provides a collection of rules for the placement of a
++      child surface relative to a parent surface. Rules can be defined to ensure
++      the child surface remains within the visible area's borders, and to
++      specify how the child surface changes its position, such as sliding along
++      an axis, or flipping around a rectangle. These positioner-created rules are
++      constrained by the requirement that a child surface must intersect with or
++      be at least partially adjacent to its parent surface.
++
++      See the various requests for details about possible rules.
++
++      At the time of the request, the compositor makes a copy of the rules
++      specified by the xdg_positioner. Thus, after the request is complete the
++      xdg_positioner object can be destroyed or reused; further changes to the
++      object will have no effect on previous usages.
++
++      For an xdg_positioner object to be considered complete, it must have a
++      non-zero size set by set_size, and a non-zero anchor rectangle set by
++      set_anchor_rect. Passing an incomplete xdg_positioner object when
++      positioning a surface raises an error.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_input" value="0" summary="invalid input provided"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_positioner object">
++      Notify the compositor that the xdg_positioner will no longer be used.
++      </description>
++    </request>
++
++    <request name="set_size">
++      <description summary="set the size of the to-be positioned rectangle">
++      Set the size of the surface that is to be positioned with the positioner
++      object. The size is in surface-local coordinates and corresponds to the
++      window geometry. See xdg_surface.set_window_geometry.
++
++      If a zero or negative size is set the invalid_input error is raised.
++      </description>
++      <arg name="width" type="int" summary="width of positioned rectangle"/>
++      <arg name="height" type="int" summary="height of positioned rectangle"/>
++    </request>
++
++    <request name="set_anchor_rect">
++      <description summary="set the anchor rectangle within the parent surface">
++      Specify the anchor rectangle within the parent surface that the child
++      surface will be placed relative to. The rectangle is relative to the
++      window geometry as defined by xdg_surface.set_window_geometry of the
++      parent surface. The rectangle must be at least 1x1 large.
++
++      When the xdg_positioner object is used to position a child surface, the
++      anchor rectangle may not extend outside the window geometry of the
++      positioned child's parent surface.
++
++      If a zero or negative size is set the invalid_input error is raised.
++      </description>
++      <arg name="x" type="int" summary="x position of anchor rectangle"/>
++      <arg name="y" type="int" summary="y position of anchor rectangle"/>
++      <arg name="width" type="int" summary="width of anchor rectangle"/>
++      <arg name="height" type="int" summary="height of anchor rectangle"/>
++    </request>
++
++    <enum name="anchor" bitfield="true">
++      <entry name="none" value="0"
++           summary="the center of the anchor rectangle"/>
++      <entry name="top" value="1"
++           summary="the top edge of the anchor rectangle"/>
++      <entry name="bottom" value="2"
++           summary="the bottom edge of the anchor rectangle"/>
++      <entry name="left" value="4"
++           summary="the left edge of the anchor rectangle"/>
++      <entry name="right" value="8"
++           summary="the right edge of the anchor rectangle"/>
++    </enum>
++
++    <request name="set_anchor">
++      <description summary="set anchor rectangle anchor edges">
++      Defines a set of edges for the anchor rectangle. These are used to
++      derive an anchor point that the child surface will be positioned
++      relative to. If two orthogonal edges are specified (e.g. 'top' and
++      'left'), then the anchor point will be the intersection of the edges
++      (e.g. the top left position of the rectangle); otherwise, the derived
++      anchor point will be centered on the specified edge, or in the center of
++      the anchor rectangle if no edge is specified.
++
++      If two parallel anchor edges are specified (e.g. 'left' and 'right'),
++      the invalid_input error is raised.
++      </description>
++      <arg name="anchor" type="uint" enum="anchor"
++         summary="bit mask of anchor edges"/>
++    </request>
++
++    <enum name="gravity" bitfield="true">
++      <entry name="none" value="0"
++           summary="center over the anchor edge"/>
++      <entry name="top" value="1"
++           summary="position above the anchor edge"/>
++      <entry name="bottom" value="2"
++           summary="position below the anchor edge"/>
++      <entry name="left" value="4"
++           summary="position to the left of the anchor edge"/>
++      <entry name="right" value="8"
++           summary="position to the right of the anchor edge"/>
++    </enum>
++
++    <request name="set_gravity">
++      <description summary="set child surface gravity">
++      Defines in what direction a surface should be positioned, relative to
++      the anchor point of the parent surface. If two orthogonal gravities are
++      specified (e.g. 'bottom' and 'right'), then the child surface will be
++      placed in the specified direction; otherwise, the child surface will be
++      centered over the anchor point on any axis that had no gravity
++      specified.
++
++      If two parallel gravities are specified (e.g. 'left' and 'right'), the
++      invalid_input error is raised.
++      </description>
++      <arg name="gravity" type="uint" enum="gravity"
++         summary="bit mask of gravity directions"/>
++    </request>
++
++    <enum name="constraint_adjustment" bitfield="true">
++      <description summary="constraint adjustments">
++      The constraint adjustment value define ways the compositor will adjust
++      the position of the surface, if the unadjusted position would result
++      in the surface being partly constrained.
++
++      Whether a surface is considered 'constrained' is left to the compositor
++      to determine. For example, the surface may be partly outside the
++      compositor's defined 'work area', thus necessitating the child surface's
++      position be adjusted until it is entirely inside the work area.
++
++      The adjustments can be combined, according to a defined precedence: 1)
++      Flip, 2) Slide, 3) Resize.
++      </description>
++      <entry name="none" value="0">
++      <description summary="don't move the child surface when constrained">
++        Don't alter the surface position even if it is constrained on some
++        axis, for example partially outside the edge of a monitor.
++      </description>
++      </entry>
++      <entry name="slide_x" value="1">
++      <description summary="move along the x axis until unconstrained">
++        Slide the surface along the x axis until it is no longer constrained.
++
++        First try to slide towards the direction of the gravity on the x axis
++        until either the edge in the opposite direction of the gravity is
++        unconstrained or the edge in the direction of the gravity is
++        constrained.
++
++        Then try to slide towards the opposite direction of the gravity on the
++        x axis until either the edge in the direction of the gravity is
++        unconstrained or the edge in the opposite direction of the gravity is
++        constrained.
++      </description>
++      </entry>
++      <entry name="slide_y" value="2">
++      <description summary="move along the y axis until unconstrained">
++        Slide the surface along the y axis until it is no longer constrained.
++
++        First try to slide towards the direction of the gravity on the y axis
++        until either the edge in the opposite direction of the gravity is
++        unconstrained or the edge in the direction of the gravity is
++        constrained.
++
++        Then try to slide towards the opposite direction of the gravity on the
++        y axis until either the edge in the direction of the gravity is
++        unconstrained or the edge in the opposite direction of the gravity is
++        constrained.
++      </description>
++      </entry>
++      <entry name="flip_x" value="4">
++      <description summary="invert the anchor and gravity on the x axis">
++        Invert the anchor and gravity on the x axis if the surface is
++        constrained on the x axis. For example, if the left edge of the
++        surface is constrained, the gravity is 'left' and the anchor is
++        'left', change the gravity to 'right' and the anchor to 'right'.
++
++        If the adjusted position also ends up being constrained, the resulting
++        position of the flip_x adjustment will be the one before the
++        adjustment.
++      </description>
++      </entry>
++      <entry name="flip_y" value="8">
++      <description summary="invert the anchor and gravity on the y axis">
++        Invert the anchor and gravity on the y axis if the surface is
++        constrained on the y axis. For example, if the bottom edge of the
++        surface is constrained, the gravity is 'bottom' and the anchor is
++        'bottom', change the gravity to 'top' and the anchor to 'top'.
++
++        If the adjusted position also ends up being constrained, the resulting
++        position of the flip_y adjustment will be the one before the
++        adjustment.
++      </description>
++      </entry>
++      <entry name="resize_x" value="16">
++      <description summary="horizontally resize the surface">
++        Resize the surface horizontally so that it is completely
++        unconstrained.
++      </description>
++      </entry>
++      <entry name="resize_y" value="32">
++      <description summary="vertically resize the surface">
++        Resize the surface vertically so that it is completely unconstrained.
++      </description>
++      </entry>
++    </enum>
++
++    <request name="set_constraint_adjustment">
++      <description summary="set the adjustment to be done when constrained">
++      Specify how the window should be positioned if the originally intended
++      position caused the surface to be constrained, meaning at least
++      partially outside positioning boundaries set by the compositor. The
++      adjustment is set by constructing a bitmask describing the adjustment to
++      be made when the surface is constrained on that axis.
++
++      If no bit for one axis is set, the compositor will assume that the child
++      surface should not change its position on that axis when constrained.
++
++      If more than one bit for one axis is set, the order of how adjustments
++      are applied is specified in the corresponding adjustment descriptions.
++
++      The default adjustment is none.
++      </description>
++      <arg name="constraint_adjustment" type="uint"
++         summary="bit mask of constraint adjustments"/>
++    </request>
++
++    <request name="set_offset">
++      <description summary="set surface position offset">
++      Specify the surface position offset relative to the position of the
++      anchor on the anchor rectangle and the anchor on the surface. For
++      example if the anchor of the anchor rectangle is at (x, y), the surface
++      has the gravity bottom|right, and the offset is (ox, oy), the calculated
++      surface position will be (x + ox, y + oy). The offset position of the
++      surface is the one used for constraint testing. See
++      set_constraint_adjustment.
++
++      An example use case is placing a popup menu on top of a user interface
++      element, while aligning the user interface element of the parent surface
++      with some user interface element placed somewhere in the popup surface.
++      </description>
++      <arg name="x" type="int" summary="surface position x offset"/>
++      <arg name="y" type="int" summary="surface position y offset"/>
++    </request>
++  </interface>
++
++  <interface name="zxdg_surface_v6" version="1">
++    <description summary="desktop user interface surface base interface">
++      An interface that may be implemented by a wl_surface, for
++      implementations that provide a desktop-style user interface.
++
++      It provides a base set of functionality required to construct user
++      interface elements requiring management by the compositor, such as
++      toplevel windows, menus, etc. The types of functionality are split into
++      xdg_surface roles.
++
++      Creating an xdg_surface does not set the role for a wl_surface. In order
++      to map an xdg_surface, the client must create a role-specific object
++      using, e.g., get_toplevel, get_popup. The wl_surface for any given
++      xdg_surface can have at most one role, and may not be assigned any role
++      not based on xdg_surface.
++
++      A role must be assigned before any other requests are made to the
++      xdg_surface object.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_surface state to take effect.
++
++      Creating an xdg_surface from a wl_surface which has a buffer attached or
++      committed is a client error, and any attempts by a client to attach or
++      manipulate a buffer prior to the first xdg_surface.configure call must
++      also be treated as errors.
++
++      For a surface to be mapped by the compositor, the following conditions
++      must be met: (1) the client has assigned an xdg_surface based role to the
++      surface, (2) the client has set and committed the xdg_surface state and
++      the role dependent state to the surface and (3) the client has committed a
++      buffer to the surface.
++    </description>
++
++    <enum name="error">
++      <entry name="not_constructed" value="1"/>
++      <entry name="already_constructed" value="2"/>
++      <entry name="unconfigured_buffer" value="3"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_surface">
++      Destroy the xdg_surface object. An xdg_surface must only be destroyed
++      after its role object has been destroyed.
++      </description>
++    </request>
++
++    <request name="get_toplevel">
++      <description summary="assign the xdg_toplevel surface role">
++      This creates an xdg_toplevel object for the given xdg_surface and gives
++      the associated wl_surface the xdg_toplevel role.
++
++      See the documentation of xdg_toplevel for more details about what an
++      xdg_toplevel is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_toplevel_v6"/>
++    </request>
++
++    <request name="get_popup">
++      <description summary="assign the xdg_popup surface role">
++      This creates an xdg_popup object for the given xdg_surface and gives the
++      associated wl_surface the xdg_popup role.
++
++      See the documentation of xdg_popup for more details about what an
++      xdg_popup is and how it is used.
++      </description>
++      <arg name="id" type="new_id" interface="zxdg_popup_v6"/>
++      <arg name="parent" type="object" interface="zxdg_surface_v6"/>
++      <arg name="positioner" type="object" interface="zxdg_positioner_v6"/>
++    </request>
++
++    <request name="set_window_geometry">
++      <description summary="set the new window geometry">
++      The window geometry of a surface is its "visible bounds" from the
++      user's perspective. Client-side decorations often have invisible
++      portions like drop-shadows which should be ignored for the
++      purposes of aligning, placing and constraining windows.
++
++      The window geometry is double buffered, and will be applied at the
++      time wl_surface.commit of the corresponding wl_surface is called.
++
++      Once the window geometry of the surface is set, it is not possible to
++      unset it, and it will remain the same until set_window_geometry is
++      called again, even if a new subsurface or buffer is attached.
++
++      If never set, the value is the full bounds of the surface,
++      including any subsurfaces. This updates dynamically on every
++      commit. This unset is meant for extremely simple clients.
++
++      The arguments are given in the surface-local coordinate space of
++      the wl_surface associated with this xdg_surface.
++
++      The width and height must be greater than zero. Setting an invalid size
++      will raise an error. When applied, the effective window geometry will be
++      the set window geometry clamped to the bounding rectangle of the
++      combined geometry of the surface of the xdg_surface and the associated
++      subsurfaces.
++      </description>
++      <arg name="x" type="int"/>
++      <arg name="y" type="int"/>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="ack_configure">
++      <description summary="ack a configure event">
++      When a configure event is received, if a client commits the
++      surface in response to the configure event, then the client
++      must make an ack_configure request sometime before the commit
++      request, passing along the serial of the configure event.
++
++      For instance, for toplevel surfaces the compositor might use this
++      information to move a surface to the top left only when the client has
++      drawn itself for the maximized or fullscreen state.
++
++      If the client receives multiple configure events before it
++      can respond to one, it only has to ack the last configure event.
++
++      A client is not required to commit immediately after sending
++      an ack_configure request - it may even ack_configure several times
++      before its next surface commit.
++
++      A client may send multiple ack_configure requests before committing, but
++      only the last request sent before a commit indicates which configure
++      event the client really is responding to.
++      </description>
++      <arg name="serial" type="uint" summary="the serial from the configure event"/>
++    </request>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++      The configure event marks the end of a configure sequence. A configure
++      sequence is a set of one or more events configuring the state of the
++      xdg_surface, including the final xdg_surface.configure event.
++
++      Where applicable, xdg_surface surface roles will during a configure
++      sequence extend this event as a latched state sent as events before the
++      xdg_surface.configure event. Such events should be considered to make up
++      a set of atomically applied configuration states, where the
++      xdg_surface.configure commits the accumulated state.
++
++      Clients should arrange their surface for the new states, and then send
++      an ack_configure request with the serial sent in this configure event at
++      some point before committing the new surface.
++
++      If the client receives multiple configure events before it can respond
++      to one, it is free to discard all but the last event it received.
++      </description>
++      <arg name="serial" type="uint" summary="serial of the configure event"/>
++    </event>
++  </interface>
++
++  <interface name="zxdg_toplevel_v6" version="1">
++    <description summary="toplevel surface">
++      This interface defines an xdg_surface role which allows a surface to,
++      among other things, set window-like properties such as maximize,
++      fullscreen, and minimize, set application-specific metadata like title and
++      id, and well as trigger user interactive operations such as interactive
++      resize and move.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the xdg_toplevel">
++      Unmap and destroy the window. The window will be effectively
++      hidden from the user's point of view, and all state like
++      maximization, fullscreen, and so on, will be lost.
++      </description>
++    </request>
++
++    <request name="set_parent">
++      <description summary="set the parent of this surface">
++      Set the "parent" of this surface. This window should be stacked
++      above a parent. The parent surface must be mapped as long as this
++      surface is mapped.
++
++      Parent windows should be set on dialogs, toolboxes, or other
++      "auxiliary" surfaces, so that the parent is raised when the dialog
++      is raised.
++      </description>
++      <arg name="parent" type="object" interface="zxdg_toplevel_v6" allow-null="true"/>
++    </request>
++
++    <request name="set_title">
++      <description summary="set surface title">
++      Set a short title for the surface.
++
++      This string may be used to identify the surface in a task bar,
++      window list, or other user interface elements provided by the
++      compositor.
++
++      The string must be encoded in UTF-8.
++      </description>
++      <arg name="title" type="string"/>
++    </request>
++
++    <request name="set_app_id">
++      <description summary="set application ID">
++      Set an application identifier for the surface.
++
++      The app ID identifies the general class of applications to which
++      the surface belongs. The compositor can use this to group multiple
++      surfaces together, or to determine how to launch a new application.
++
++      For D-Bus activatable applications, the app ID is used as the D-Bus
++      service name.
++
++      The compositor shell will try to group application surfaces together
++      by their app ID. As a best practice, it is suggested to select app
++      ID's that match the basename of the application's .desktop file.
++      For example, "org.freedesktop.FooViewer" where the .desktop file is
++      "org.freedesktop.FooViewer.desktop".
++
++      See the desktop-entry specification [0] for more details on
++      application identifiers and how they relate to well-known D-Bus
++      names and .desktop files.
++
++      [0] http://standards.freedesktop.org/desktop-entry-spec/
++      </description>
++      <arg name="app_id" type="string"/>
++    </request>
++
++    <request name="show_window_menu">
++      <description summary="show the window menu">
++      Clients implementing client-side decorations might want to show
++      a context menu when right-clicking on the decorations, giving the
++      user a menu that they can use to maximize or minimize the window.
++
++      This request asks the compositor to pop up such a window menu at
++      the given position, relative to the local surface coordinates of
++      the parent surface. There are no guarantees as to what menu items
++      the window menu contains.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="x" type="int" summary="the x position to pop up the window menu at"/>
++      <arg name="y" type="int" summary="the y position to pop up the window menu at"/>
++    </request>
++
++    <request name="move">
++      <description summary="start an interactive move">
++      Start an interactive, user-driven move of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive move (touch,
++      pointer, etc).
++
++      The server may ignore move requests depending on the state of
++      the surface (e.g. fullscreen or maximized), or if the passed serial
++      is no longer valid.
++
++      If triggered, the surface will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the move. It is up to the
++      compositor to visually indicate that the move is taking place, such as
++      updating a pointer cursor, during the move. There is no guarantee
++      that the device focus will return when the move is completed.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++    </request>
++
++    <enum name="resize_edge">
++      <description summary="edge values for resizing">
++      These values are used to indicate which edge of a surface
++      is being dragged in a resize operation.
++      </description>
++      <entry name="none" value="0"/>
++      <entry name="top" value="1"/>
++      <entry name="bottom" value="2"/>
++      <entry name="left" value="4"/>
++      <entry name="top_left" value="5"/>
++      <entry name="bottom_left" value="6"/>
++      <entry name="right" value="8"/>
++      <entry name="top_right" value="9"/>
++      <entry name="bottom_right" value="10"/>
++    </enum>
++
++    <request name="resize">
++      <description summary="start an interactive resize">
++      Start a user-driven, interactive resize of the surface.
++
++      This request must be used in response to some sort of user action
++      like a button press, key press, or touch down event. The passed
++      serial is used to determine the type of interactive resize (touch,
++      pointer, etc).
++
++      The server may ignore resize requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++
++      If triggered, the client will receive configure events with the
++      "resize" state enum value and the expected sizes. See the "resize"
++      enum value for more details about what is required. The client
++      must also acknowledge configure events using "ack_configure". After
++      the resize is completed, the client will receive another "configure"
++      event without the resize state.
++
++      If triggered, the surface also will lose the focus of the device
++      (wl_pointer, wl_touch, etc) used for the resize. It is up to the
++      compositor to visually indicate that the resize is taking place,
++      such as updating a pointer cursor, during the resize. There is no
++      guarantee that the device focus will return when the resize is
++      completed.
++
++      The edges parameter specifies how the surface should be resized,
++      and is one of the values of the resize_edge enum. The compositor
++      may use this information to update the surface position for
++      example when dragging the top left corner. The compositor may also
++      use this information to adapt its behavior, e.g. choose an
++      appropriate cursor image.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++      <arg name="edges" type="uint" summary="which edge or corner is being dragged"/>
++    </request>
++
++    <enum name="state">
++      <description summary="types of state on the surface">
++      The different state values used on the surface. This is designed for
++      state values like maximized, fullscreen. It is paired with the
++      configure event to ensure that both the client and the compositor
++      setting the state can be synchronized.
++
++      States set in this way are double-buffered. They will get applied on
++      the next commit.
++      </description>
++      <entry name="maximized" value="1" summary="the surface is maximized">
++      <description summary="the surface is maximized">
++        The surface is maximized. The window geometry specified in the configure
++        event must be obeyed by the client.
++      </description>
++      </entry>
++      <entry name="fullscreen" value="2" summary="the surface is fullscreen">
++      <description summary="the surface is fullscreen">
++        The surface is fullscreen. The window geometry specified in the configure
++        event must be obeyed by the client.
++      </description>
++      </entry>
++      <entry name="resizing" value="3" summary="the surface is being resized">
++      <description summary="the surface is being resized">
++        The surface is being resized. The window geometry specified in the
++        configure event is a maximum; the client cannot resize beyond it.
++        Clients that have aspect ratio or cell sizing configuration can use
++        a smaller size, however.
++      </description>
++      </entry>
++      <entry name="activated" value="4" summary="the surface is now activated">
++      <description summary="the surface is now activated">
++        Client window decorations should be painted as if the window is
++        active. Do not assume this means that the window actually has
++        keyboard or pointer focus.
++      </description>
++      </entry>
++    </enum>
++
++    <request name="set_max_size">
++      <description summary="set the maximum size">
++      Set a maximum size for the window.
++
++      The client can specify a maximum size so that the compositor does
++      not try to configure the window beyond this size.
++
++      The width and height arguments are in window geometry coordinates.
++      See xdg_surface.set_window_geometry.
++
++      Values set in this way are double-buffered. They will get applied
++      on the next commit.
++
++      The compositor can use this information to allow or disallow
++      different states like maximize or fullscreen and draw accurate
++      animations.
++
++      Similarly, a tiling window manager may use this information to
++      place and resize client windows in a more effective way.
++
++      The client should not rely on the compositor to obey the maximum
++      size. The compositor may decide to ignore the values set by the
++      client and request a larger size.
++
++      If never set, or a value of zero in the request, means that the
++      client has no expected maximum size in the given dimension.
++      As a result, a client wishing to reset the maximum size
++      to an unspecified state can use zero for width and height in the
++      request.
++
++      Requesting a maximum size to be smaller than the minimum size of
++      a surface is illegal and will result in a protocol error.
++
++      The width and height must be greater than or equal to zero. Using
++      strictly negative values for width and height will result in a
++      protocol error.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_min_size">
++      <description summary="set the minimum size">
++      Set a minimum size for the window.
++
++      The client can specify a minimum size so that the compositor does
++      not try to configure the window below this size.
++
++      The width and height arguments are in window geometry coordinates.
++      See xdg_surface.set_window_geometry.
++
++      Values set in this way are double-buffered. They will get applied
++      on the next commit.
++
++      The compositor can use this information to allow or disallow
++      different states like maximize or fullscreen and draw accurate
++      animations.
++
++      Similarly, a tiling window manager may use this information to
++      place and resize client windows in a more effective way.
++
++      The client should not rely on the compositor to obey the minimum
++      size. The compositor may decide to ignore the values set by the
++      client and request a smaller size.
++
++      If never set, or a value of zero in the request, means that the
++      client has no expected minimum size in the given dimension.
++      As a result, a client wishing to reset the minimum size
++      to an unspecified state can use zero for width and height in the
++      request.
++
++      Requesting a minimum size to be larger than the maximum size of
++      a surface is illegal and will result in a protocol error.
++
++      The width and height must be greater than or equal to zero. Using
++      strictly negative values for width and height will result in a
++      protocol error.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++    </request>
++
++    <request name="set_maximized">
++      <description summary="maximize the window">
++      Maximize the surface.
++
++      After requesting that the surface should be maximized, the compositor
++      will respond by emitting a configure event with the "maximized" state
++      and the required window geometry. The client should then update its
++      content, drawing it in a maximized state, i.e. without shadow or other
++      decoration outside of the window geometry. The client must also
++      acknowledge the configure when committing the new content (see
++      ack_configure).
++
++      It is up to the compositor to decide how and where to maximize the
++      surface, for example which output and what region of the screen should
++      be used.
++
++      If the surface was already maximized, the compositor will still emit
++      a configure event with the "maximized" state.
++      </description>
++    </request>
++
++    <request name="unset_maximized">
++      <description summary="unmaximize the window">
++      Unmaximize the surface.
++
++      After requesting that the surface should be unmaximized, the compositor
++      will respond by emitting a configure event without the "maximized"
++      state. If available, the compositor will include the window geometry
++      dimensions the window had prior to being maximized in the configure
++      request. The client must then update its content, drawing it in a
++      regular state, i.e. potentially with shadow, etc. The client must also
++      acknowledge the configure when committing the new content (see
++      ack_configure).
++
++      It is up to the compositor to position the surface after it was
++      unmaximized; usually the position the surface had before maximizing, if
++      applicable.
++
++      If the surface was already not maximized, the compositor will still
++      emit a configure event without the "maximized" state.
++      </description>
++    </request>
++
++    <request name="set_fullscreen">
++      <description summary="set the window as fullscreen on a monitor">
++      Make the surface fullscreen.
++
++      You can specify an output that you would prefer to be fullscreen.
++      If this value is NULL, it's up to the compositor to choose which
++      display will be used to map this surface.
++
++      If the surface doesn't cover the whole output, the compositor will
++      position the surface in the center of the output and compensate with
++      black borders filling the rest of the output.
++      </description>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"/>
++    </request>
++    <request name="unset_fullscreen" />
++
++    <request name="set_minimized">
++      <description summary="set the window as minimized">
++      Request that the compositor minimize your surface. There is no
++      way to know if the surface is currently minimized, nor is there
++      any way to unset minimization on this surface.
++
++      If you are looking to throttle redrawing when minimized, please
++      instead use the wl_surface.frame event for this, as this will
++      also work with live previews on windows in Alt-Tab, Expose or
++      similar compositor features.
++      </description>
++    </request>
++
++    <event name="configure">
++      <description summary="suggest a surface change">
++      This configure event asks the client to resize its toplevel surface or
++      to change its state. The configured state should not be applied
++      immediately. See xdg_surface.configure for details.
++
++      The width and height arguments specify a hint to the window
++      about how its surface should be resized in window geometry
++      coordinates. See set_window_geometry.
++
++      If the width or height arguments are zero, it means the client
++      should decide its own window dimension. This may happen when the
++      compositor needs to configure the state of the surface but doesn't
++      have any information about any previous or expected dimension.
++
++      The states listed in the event specify how the width/height
++      arguments should be interpreted, and possibly how it should be
++      drawn.
++
++      Clients must send an ack_configure in response to this event. See
++      xdg_surface.configure and xdg_surface.ack_configure for details.
++      </description>
++      <arg name="width" type="int"/>
++      <arg name="height" type="int"/>
++      <arg name="states" type="array"/>
++    </event>
++
++    <event name="close">
++      <description summary="surface wants to be closed">
++      The close event is sent by the compositor when the user
++      wants the surface to be closed. This should be equivalent to
++      the user clicking the close button in client-side decorations,
++      if your application has any.
++
++      This is only a request that the user intends to close the
++      window. The client may choose to ignore this request, or show
++      a dialog to ask the user to save their data, etc.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="zxdg_popup_v6" version="1">
++    <description summary="short-lived, popup surfaces for menus">
++      A popup surface is a short-lived, temporary surface. It can be used to
++      implement for example menus, popovers, tooltips and other similar user
++      interface concepts.
++
++      A popup can be made to take an explicit grab. See xdg_popup.grab for
++      details.
++
++      When the popup is dismissed, a popup_done event will be sent out, and at
++      the same time the surface will be unmapped. See the xdg_popup.popup_done
++      event for details.
++
++      Explicitly destroying the xdg_popup object will also dismiss the popup and
++      unmap the surface. Clients that want to dismiss the popup when another
++      surface of their own is clicked should dismiss the popup using the destroy
++      request.
++
++      The parent surface must have either the xdg_toplevel or xdg_popup surface
++      role.
++
++      A newly created xdg_popup will be stacked on top of all previously created
++      xdg_popup surfaces associated with the same xdg_toplevel.
++
++      The parent of an xdg_popup must be mapped (see the xdg_surface
++      description) before the xdg_popup itself.
++
++      The x and y arguments passed when creating the popup object specify
++      where the top left of the popup should be placed, relative to the
++      local surface coordinates of the parent surface. See
++      xdg_surface.get_popup. An xdg_popup must intersect with or be at least
++      partially adjacent to its parent surface.
++
++      The client must call wl_surface.commit on the corresponding wl_surface
++      for the xdg_popup state to take effect.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_grab" value="0"
++           summary="tried to grab after being mapped"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove xdg_popup interface">
++      This destroys the popup. Explicitly destroying the xdg_popup
++      object will also dismiss the popup, and unmap the surface.
++
++      If this xdg_popup is not the "topmost" popup, a protocol error
++      will be sent.
++      </description>
++    </request>
++
++    <request name="grab">
++      <description summary="make the popup take an explicit grab">
++      This request makes the created popup take an explicit grab. An explicit
++      grab will be dismissed when the user dismisses the popup, or when the
++      client destroys the xdg_popup. This can be done by the user clicking
++      outside the surface, using the keyboard, or even locking the screen
++      through closing the lid or a timeout.
++
++      If the compositor denies the grab, the popup will be immediately
++      dismissed.
++
++      This request must be used in response to some sort of user action like a
++      button press, key press, or touch down event. The serial number of the
++      event should be passed as 'serial'.
++
++      The parent of a grabbing popup must either be an xdg_toplevel surface or
++      another xdg_popup with an explicit grab. If the parent is another
++      xdg_popup it means that the popups are nested, with this popup now being
++      the topmost popup.
++
++      Nested popups must be destroyed in the reverse order they were created
++      in, e.g. the only popup you are allowed to destroy at all times is the
++      topmost one.
++
++      When compositors choose to dismiss a popup, they may dismiss every
++      nested grabbing popup as well. When a compositor dismisses popups, it
++      will follow the same dismissing order as required from the client.
++
++      The parent of a grabbing popup must either be another xdg_popup with an
++      active explicit grab, or an xdg_popup or xdg_toplevel, if there are no
++      explicit grabs already taken.
++
++      If the topmost grabbing popup is destroyed, the grab will be returned to
++      the parent of the popup, if that parent previously had an explicit grab.
++
++      If the parent is a grabbing popup which has already been dismissed, this
++      popup will be immediately dismissed. If the parent is a popup that did
++      not take an explicit grab, an error will be raised.
++
++      During a popup grab, the client owning the grab will receive pointer
++      and touch events for all their surfaces as normal (similar to an
++      "owner-events" grab in X11 parlance), while the top most grabbing popup
++      will always have keyboard focus.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat"
++         summary="the wl_seat of the user event"/>
++      <arg name="serial" type="uint" summary="the serial of the user event"/>
++    </request>
++
++    <event name="configure">
++      <description summary="configure the popup surface">
++      This event asks the popup surface to configure itself given the
++      configuration. The configured state should not be applied immediately.
++      See xdg_surface.configure for details.
++
++      The x and y arguments represent the position the popup was placed at
++      given the xdg_positioner rule, relative to the upper left corner of the
++      window geometry of the parent surface.
++      </description>
++      <arg name="x" type="int"
++         summary="x position relative to parent surface window geometry"/>
++      <arg name="y" type="int"
++         summary="y position relative to parent surface window geometry"/>
++      <arg name="width" type="int" summary="window geometry width"/>
++      <arg name="height" type="int" summary="window geometry height"/>
++    </event>
++
++    <event name="popup_done">
++      <description summary="popup interaction is done">
++      The popup_done event is sent out when a popup is dismissed by the
++      compositor. The client should destroy the xdg_popup object at this
++      point.
++      </description>
++    </event>
++
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dbe45a5066620c8b4c1eb0338064384865b0bf58
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++Xwayland keyboard grabbing protocol
++
++Maintainers:
++Olivier Fourdan <ofourdan@redhat.com>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..be4992fd72db99a0902606161d108eb39ceef56f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,121 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="xwayland_keyboard_grab_unstable_v1">
++
++  <copyright>
++    Copyright © 2017 Red Hat Inc.
++
++    Permission is hereby granted, free of charge, to any person obtaining a
++    copy of this software and associated documentation files (the "Software"),
++    to deal in the Software without restriction, including without limitation
++    the rights to use, copy, modify, merge, publish, distribute, sublicense,
++    and/or sell copies of the Software, and to permit persons to whom the
++    Software is furnished to do so, subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the next
++    paragraph) shall be included in all copies or substantial portions of the
++    Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++    DEALINGS IN THE SOFTWARE.
++  </copyright>
++
++  <description summary="Protocol for grabbing the keyboard from Xwayland">
++    This protocol is application-specific to meet the needs of the X11
++    protocol through Xwayland. It provides a way for Xwayland to request
++    all keyboard events to be forwarded to a surface even when the
++    surface does not have keyboard focus.
++
++    In the X11 protocol, a client may request an "active grab" on the
++    keyboard. On success, all key events are reported only to the
++    grabbing X11 client. For details, see XGrabKeyboard(3).
++
++    The core Wayland protocol does not have a notion of an active
++    keyboard grab. When running in Xwayland, X11 applications may
++    acquire an active grab inside Xwayland but that cannot be translated
++    to the Wayland compositor who may set the input focus to some other
++    surface. In doing so, it breaks the X11 client assumption that all
++    key events are reported to the grabbing client.
++
++    This protocol specifies a way for Xwayland to request all keyboard
++    be directed to the given surface. The protocol does not guarantee
++    that the compositor will honor this request and it does not
++    prescribe user interfaces on how to handle the respond. For example,
++    a compositor may inform the user that all key events are now
++    forwarded to the given client surface, or it may ask the user for
++    permission to do so.
++
++    Compositors are required to restrict access to this application
++    specific protocol to Xwayland alone.
++
++    Warning! The protocol described in this file is experimental and
++    backward incompatible changes may be made. Backward compatible
++    changes may be added together with the corresponding interface
++    version bump.
++    Backward incompatible changes are done by bumping the version
++    number in the protocol and interface names and resetting the
++    interface version. Once the protocol is to be declared stable,
++    the 'z' prefix and the version number in the protocol and
++    interface names are removed and the interface version number is
++    reset.
++  </description>
++
++  <interface name="zwp_xwayland_keyboard_grab_manager_v1" version="1">
++    <description summary="context object for keyboard grab manager">
++      A global interface used for grabbing the keyboard.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the keyboard grab manager">
++      Destroy the keyboard grab manager.
++      </description>
++    </request>
++
++    <request name="grab_keyboard">
++      <description summary="grab the keyboard to a surface">
++      The grab_keyboard request asks for a grab of the keyboard, forcing
++      the keyboard focus for the given seat upon the given surface.
++
++      The protocol provides no guarantee that the grab is ever satisfied,
++      and does not require the compositor to send an error if the grab
++      cannot ever be satisfied. It is thus possible to request a keyboard
++      grab that will never be effective.
++
++      The protocol:
++
++      * does not guarantee that the grab itself is applied for a surface,
++        the grab request may be silently ignored by the compositor,
++      * does not guarantee that any events are sent to this client even
++        if the grab is applied to a surface,
++      * does not guarantee that events sent to this client are exhaustive,
++        a compositor may filter some events for its own consumption,
++      * does not guarantee that events sent to this client are continuous,
++        a compositor may change and reroute keyboard events while the grab
++        is nominally active.
++      </description>
++
++      <arg name="id" type="new_id" interface="zwp_xwayland_keyboard_grab_v1"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="surface to report keyboard events to"/>
++      <arg name="seat" type="object" interface="wl_seat"
++         summary="the seat for which the keyboard should be grabbed"/>
++    </request>
++  </interface>
++
++  <interface name="zwp_xwayland_keyboard_grab_v1" version="1">
++    <description summary="interface for grabbing the keyboard">
++      A global interface used for grabbing the keyboard.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the grabbed keyboard object">
++      Destroy the grabbed keyboard object. If applicable, the compositor
++      will ungrab the keyboard.
++      </description>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..cf7adf257a79c894d19f7241c354840d818b70b9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++pkgdatadir=@abs_top_srcdir@
++
++Name: Wayland Protocols
++Description: Wayland protocol files (not installed)
++Version: @WAYLAND_PROTOCOLS_VERSION@
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4571fa8180b163a4f887f70af697876dcfa01726
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++prefix=@prefix@
++datarootdir=@datarootdir@
++pkgdatadir=${pc_sysrootdir}${datarootdir}/@PACKAGE@
++
++Name: Wayland Protocols
++Description: Wayland protocol files
++Version: @WAYLAND_PROTOCOLS_VERSION@
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d92e5e965f3c7a5946fc70fcd2b883dc827d49cc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,24 @@@
++root = true
++
++[*]
++charset = utf-8
++end_of_line = lf
++trim_trailing_whitespace = true
++insert_final_newline = true
++indent_style = tab
++indent_size = 8
++max_line_length = 80
++
++[*.xml]
++indent_style = tab
++indent_size = 2
++tab_width = 8
++
++[*.py]
++indent_style = space
++indent_size = 4
++
++[*.yml]
++indent_style = space
++indent_size = 2
++max_line_length = off
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4fefe5d33e88f4fdffb68cd36edd740a12be2b03
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++*.announce
++*.sig
++*.swp
++*.log
++*.tar.xz
++*~
++cscope.out
++ctags
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..db5c9c3099aeaa84b7575e2c802ec2f6fbc415ca
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,350 @@@
++# This file uses the freedesktop ci-templates to build Wayland and run our
++# tests in CI.
++#
++# ci-templates uses a multi-stage build process. First, the base container
++# image is built which contains the core distribution, the toolchain, and
++# all our build dependencies. This container is aggressively cached; if a
++# container image matching $FDO_DISTRIBUTION_TAG is found in either the
++# upstream repo (wayland/weston) or the user's downstream repo, it is
++# reused for the build. This gives us predictability of build and far
++# quicker runtimes, however it means that any changes to the base container
++# must also change $FDO_DISTRIBUTION_TAG. When changing this, please use
++# the current date as well as a unique build identifier.
++#
++# After the container is either rebuilt (tag mismatch) or reused (tag
++# previously used), the build stage executes within this container.
++#
++# The final stage is used to expose documentation and coverage information,
++# including publishing documentation to the public site when built on the
++# main branch.
++#
++# Apart from the 'variables', 'include', and 'stages' top-level anchors,
++# everything not beginning with a dot ('.') is the name of a job which will
++# be executed as part of CI, unless the rules specify that it should not be
++# run.
++#
++# Variables prefixed with CI_ are generally provided by GitLab itself;
++# variables prefixed with FDO_ and templates prefixed by .fdo are provided
++# by the ci-templates.
++#
++# For more information on GitLab CI, including the YAML syntax, see:
++#   https://docs.gitlab.com/ee/ci/yaml/README.html
++#
++# Note that freedesktop.org uses the 'Community Edition' of GitLab, so features
++# marked as 'premium' or 'ultimate' are not available to us.
++#
++# For more information on ci-templates, see:
++#   - documentation at https://freedesktop.pages.freedesktop.org/ci-templates/
++#   - repo at https://gitlab.freedesktop.org/freedesktop/ci-templates/
++
++# Here we use a fixed ref in order to isolate ourselves from ci-templates
++# API changes. If you need new features from ci-templates you must bump
++# this to the current SHA you require from the ci-templates repo, however
++# be aware that you may need to account for API changes when doing so.
++.templates_sha: &template_sha 567700e483aabed992d0a4fea84994a0472deff6 # see https://docs.gitlab.com/ee/ci/yaml/#includefile
++
++include:
++  - project: 'freedesktop/ci-templates'
++    ref: *template_sha
++    file:
++      - '/templates/debian.yml'
++      - '/templates/freebsd.yml'
++      - '/templates/ci-fairy.yml'
++
++variables:
++  FDO_UPSTREAM_REPO: wayland/wayland
++  FDO_REPO_SUFFIX: "$BUILD_OS/$BUILD_ARCH"
++
++
++# Define the build stages. These are used for UI grouping as well as
++# dependencies.
++stages:
++  - "Merge request checks"
++  - "Base container"
++  - "Build and test"
++  - "Other build configurations"
++
++.ci-rules:
++  rules:
++    - when: on_success
++
++# Base variables used for anything using a Debian environment
++.os-debian:
++  variables:
++    BUILD_OS: debian
++    FDO_DISTRIBUTION_VERSION: buster
++    FDO_DISTRIBUTION_PACKAGES: 'build-essential pkg-config libexpat1-dev libffi-dev libxml2-dev doxygen graphviz xmlto xsltproc docbook-xsl python3-pip python3-setuptools ninja-build'
++    FDO_DISTRIBUTION_EXEC: 'pip3 install meson==0.56.0'
++    # bump this tag every time you change something which requires rebuilding the
++    # base image
++    FDO_DISTRIBUTION_TAG: "2022-02-05.0"
++
++.debian-x86_64:
++  extends:
++    - .os-debian
++  variables:
++    BUILD_ARCH: "x86-64"
++
++.debian-aarch64:
++  extends:
++    - .os-debian
++  variables:
++    BUILD_ARCH: "aarch64"
++
++.debian-armv7:
++  extends:
++    - .os-debian
++  variables:
++    BUILD_ARCH: "armv7"
++
++
++# Does not inherit .ci-rules as we only want it to run in MR context.
++check-commit:
++  extends:
++    - .fdo.ci-fairy
++  stage: "Merge request checks"
++  rules:
++    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
++      when: always
++    - when: never
++  script:
++    - ci-fairy check-commits --signed-off-by --junit-xml=results.xml
++  variables:
++    GIT_DEPTH: 100
++  artifacts:
++    reports:
++      junit: results.xml
++
++
++# Build our base container image, which contains the core distribution, the
++# toolchain, and all our build dependencies. This will be reused in the build
++# stage.
++x86_64-debian-container_prep:
++  extends:
++    - .ci-rules
++    - .debian-x86_64
++    - .fdo.container-build@debian
++  stage: "Base container"
++  variables:
++    GIT_STRATEGY: none
++
++aarch64-debian-container_prep:
++  extends:
++    - .ci-rules
++    - .debian-aarch64
++    - .fdo.container-build@debian
++  tags:
++    - aarch64
++  stage: "Base container"
++  variables:
++    GIT_STRATEGY: none
++
++armv7-debian-container_prep:
++  extends:
++    - .ci-rules
++    - .debian-armv7
++    - .fdo.container-build@debian
++  tags:
++    - aarch64
++  stage: "Base container"
++  variables:
++    GIT_STRATEGY: none
++    FDO_BASE_IMAGE: "arm32v7/debian:$FDO_DISTRIBUTION_VERSION"
++
++
++# Core build environment.
++.build-env:
++  variables:
++    MESON_BUILD_TYPE: "-Dbuildtype=debug -Doptimization=0 -Db_sanitize=address,undefined"
++  before_script:
++    - export BUILD_ID="wayland-$CI_JOB_NAME"
++    - export PREFIX="${CI_PROJECT_DIR}/prefix-${BUILD_ID}"
++    - export BUILDDIR="${CI_PROJECT_DIR}/build-${BUILD_ID}"
++    - mkdir "$BUILDDIR" "$PREFIX"
++
++
++# Build variants to be stacked on as required.
++.build-release:
++  stage: "Other build configurations"
++  variables:
++    MESON_BUILD_TYPE: "-Dbuildtype=release"
++
++
++# OS/architecture-specific variants
++.build-env-debian-x86_64:
++  extends:
++    - .fdo.suffixed-image@debian
++    - .debian-x86_64
++    - .build-env
++  needs:
++    - job: x86_64-debian-container_prep
++      artifacts: false
++
++.build-env-debian-aarch64:
++  extends:
++    - .fdo.suffixed-image@debian
++    - .debian-aarch64
++    - .build-env
++  variables:
++    # At least with the versions we have, the LSan runtime makes fork unusably
++    # slow on AArch64, which is bad news since the test suite decides to fork
++    # for every single subtest. For now, in order to get AArch64 builds and
++    # tests into CI, just assume that we're not going to leak any more on
++    # AArch64 than we would on ARMv7 or x86-64.
++    ASAN_OPTIONS: "detect_leaks=0"
++  tags:
++    - aarch64
++  needs:
++    - job: aarch64-debian-container_prep
++      artifacts: false
++
++.build-env-debian-armv7:
++  extends:
++    - .fdo.suffixed-image@debian
++    - .debian-armv7
++    - .build-env
++  tags:
++    - aarch64
++  needs:
++    - job: armv7-debian-container_prep
++      artifacts: false
++
++
++# Full build and test.
++.do-build:
++  extends:
++    - .ci-rules
++  stage: "Build and test"
++  script:
++    - cd "$BUILDDIR"
++    - meson --prefix="$PREFIX" -Dicon_directory=/usr/share/X11/icons -Dwerror=true ${MESON_BUILD_TYPE} ..
++    - ninja -k0 -j${FDO_CI_CONCURRENT:-4}
++    - meson test --num-processes ${FDO_CI_CONCURRENT:-4}
++    - ninja clean
++  artifacts:
++    name: wayland-$CI_JOB_NAME
++    when: always
++    paths:
++      - build-*/meson-logs
++      - prefix-*
++    reports:
++      junit: build-*/meson-logs/testlog.junit.xml
++
++# Full build and test.
++.do-build-qemu:
++  extends:
++    - .ci-rules
++  stage: "Build and test"
++  script:
++    # Start the VM and copy our workspace to the VM
++    - /app/vmctl start
++    - scp -r $PWD "vm:"
++    # The `set +e is needed to ensure that we always copy the meson logs back to
++    # the workspace to see details about the failed tests.
++    - |
++      set +e
++      /app/vmctl exec "pkg info; cd $CI_PROJECT_NAME ; meson $BUILDDIR --prefix=$PREFIX $MESON_BUILD_TYPE $MESON_ARGS && ninja -C $BUILDDIR -j${FDO_CI_CONCURRENT:-4}"
++      /app/vmctl exec "meson test --print-errorlogs -C $BUILDDIR --num-processes ${FDO_CI_CONCURRENT:-4}" && touch .tests-successful
++      set -ex
++      scp -r vm:$BUILDDIR/meson-logs .
++      /app/vmctl exec "ninja -C $BUILDDIR install"
++      mkdir -p $PREFIX && scp -r vm:$PREFIX/ $PREFIX/
++    # Finally, shut down the VM.
++    - /app/vmctl stop
++    - test -f .tests-successful || exit 1
++  artifacts:
++    name: wayland-$CI_JOB_NAME
++    when: always
++    paths:
++      - meson-logs
++      - prefix-*
++    reports:
++      junit: meson-logs/testlog.junit.xml
++
++# Full build and test.
++x86_64-debian-build:
++  extends:
++    - .build-env-debian-x86_64
++    - .do-build
++
++x86_64-release-debian-build:
++  extends:
++    - .build-env-debian-x86_64
++    - .do-build
++    - .build-release
++
++aarch64-debian-build:
++  extends:
++    - .build-env-debian-aarch64
++    - .do-build
++
++aarch64-release-debian-build:
++  extends:
++    - .build-env-debian-aarch64
++    - .do-build
++    - .build-release
++
++armv7-debian-build:
++  extends:
++    - .build-env-debian-armv7
++    - .do-build
++
++armv7-release-debian-build:
++  extends:
++    - .build-env-debian-armv7
++    - .do-build
++    - .build-release
++
++# Base variables used for anything using a FreeBSD environment
++.os-freebsd:
++  variables:
++    BUILD_OS: freebsd
++    FDO_DISTRIBUTION_VERSION: "13.0"
++    FDO_DISTRIBUTION_PACKAGES: 'libxslt meson ninja pkgconf expat libffi libepoll-shim libxml2'
++    # bump this tag every time you change something which requires rebuilding the
++    # base image
++    FDO_DISTRIBUTION_TAG: "2021-08-05.0"
++    # Don't build documentation since installing the required tools massively
++    # increases the VM image (and therefore container) size.
++    MESON_ARGS: "-Ddocumentation=false"
++
++.freebsd-x86_64:
++  extends:
++    - .os-freebsd
++  variables:
++    BUILD_ARCH: "x86_64"
++
++x86_64-freebsd-container_prep:
++  extends:
++    - .ci-rules
++    - .freebsd-x86_64
++    - .fdo.qemu-build@freebsd@x86_64
++  stage: "Base container"
++  variables:
++    GIT_STRATEGY: none
++
++.build-env-freebsd-x86_64:
++  variables:
++    # Compiling with ASan+UBSan appears to trigger an infinite loop in the
++    # compiler shipped with FreeBSD 13.0, so we only use UBSan here.
++    # Additionally, sanitizers can't be used with b_lundef on FreeBSD.
++    MESON_BUILD_TYPE: "-Dbuildtype=debug -Db_sanitize=undefined -Db_lundef=false"
++  extends:
++    - .fdo.suffixed-image@freebsd
++    - .freebsd-x86_64
++    - .build-env
++  needs:
++    - job: x86_64-freebsd-container_prep
++      artifacts: false
++
++# Full build and test.
++x86_64-freebsd-build:
++  extends:
++    - .build-env-freebsd-x86_64
++    - .do-build-qemu
++
++x86_64-release-freebsd-build:
++  extends:
++    - .build-env-freebsd-x86_64
++    - .do-build-qemu
++    - .build-release
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b78a615377b2c836dc0de5954b6d505cdffdb2ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++<!--
++This repository is for the Wayland protocol description and the libwayland IPC helper
++library only. Issues with Wayland during day-to-day usage are almost
++certainly a bug in your compositor and **not** a bug with in this
++repository.
++
++Please remove this comment before filing your bug.
++-->
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1ea351f053c14e046133225d6f6d41f294235973
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,344 @@@
++Contributing to Wayland
++=======================
++
++Sending patches
++---------------
++
++Patches should be sent via
++[GitLab merge requests](https://docs.gitlab.com/ce/gitlab-basics/add-merge-request.html).
++Wayland is
++[hosted on freedesktop.org's GitLab](https://gitlab.freedesktop.org/wayland/wayland/):
++in order to submit code, you should create an account on this GitLab instance,
++fork the core Wayland repository, push your changes to a branch in your new
++repository, and then submit these patches for review through a merge request.
++
++Wayland formerly accepted patches via `git-send-email`, sent to
++**wayland-devel@lists.freedesktop.org**; these were
++[tracked using Patchwork](https://patchwork.freedesktop.org/project/wayland/).
++Some old patches continue to be sent this way, and we may accept small new
++patches sent to the list, but please send all new patches through GitLab merge
++requests.
++
++
++Formatting and separating commits
++---------------------------------
++
++Unlike many projects using GitHub and GitLab, Wayland has a
++[linear, 'recipe' style history](http://www.bitsnbites.eu/git-history-work-log-vs-recipe/).
++This means that every commit should be small, digestible, stand-alone, and
++functional. Rather than a purely chronological commit history like this:
++
++    connection: plug a fd leak
++    plug another fd leak
++    connection: init fds to -1
++    close all fds
++    refactor checks into a new function
++    don't close fds we handed out
++
++we aim to have a clean history which only reflects the final state, broken up
++into functional groupings:
++
++    connection: Refactor out closure allocation
++    connection: Clear fds we shouldn't close to -1
++    connection: Make wl_closure_destroy() close fds of undispatched closures
++
++This ensures that the final patch series only contains the final state,
++without the changes and missteps taken along the development process.
++
++The first line of a commit message should contain a prefix indicating
++what part is affected by the patch followed by one sentence that
++describes the change. For examples:
++
++    protocol: Support scaled outputs and surfaces
++
++and
++
++    doc: generate server documentation from XML too
++
++If in doubt what prefix to use, look at other commits that change the
++same file(s) as the patch being sent.
++
++The body of the commit message should describe what the patch changes
++and why, and also note any particular side effects. This shouldn't be
++empty on most of the cases. It shouldn't take a lot of effort to write
++a commit message for an obvious change, so an empty commit message
++body is only acceptable if the questions "What?" and "Why?" are already
++answered on the one-line summary.
++
++The lines of the commit message should have at most 76 characters, to
++cope with the way git log presents them.
++
++See [notes on commit messages] for a recommended reading on writing commit
++messages.
++
++Your patches should also include a Signed-off-by line with your name and
++email address.  If you're not the patch's original author, you should
++also gather S-o-b's by them (and/or whomever gave the patch to you.) The
++significance of this is that it certifies that you created the patch,
++that it was created under an appropriate open source license, or
++provided to you under those terms.  This lets us indicate a chain of
++responsibility for the copyright status of the code.
++
++We won't reject patches that lack S-o-b, but it is strongly recommended.
++
++When you re-send patches, revised or not, it would be very good to document the
++changes compared to the previous revision in the commit message and/or the
++merge request. If you have already received Reviewed-by or Acked-by tags, you
++should evaluate whether they still apply and include them in the respective
++commit messages. Otherwise the tags may be lost, reviewers miss the credit they
++deserve, and the patches may cause redundant review effort.
++
++
++Tracking patches and following up
++---------------------------------
++
++Once submitted to GitLab, your patches will be reviewed by the Wayland
++development team on GitLab. Review may be entirely positive and result in your
++code landing instantly, in which case, great! You're done. However, we may ask
++you to make some revisions: fixing some bugs we've noticed, working to a
++slightly different design, or adding documentation and tests.
++
++If you do get asked to revise the patches, please bear in mind the notes above.
++You should use `git rebase -i` to make revisions, so that your patches follow
++the clear linear split documented above. Following that split makes it easier
++for reviewers to understand your work, and to verify that the code you're
++submitting is correct.
++
++A common request is to split single large patch into multiple patches. This can
++happen, for example, if when adding a new feature you notice a bug elsewhere
++which you need to fix to progress. Separating these changes into separate
++commits will allow us to verify and land the bugfix quickly, pushing part of
++your work for the good of everyone, whilst revision and discussion continues on
++the larger feature part. It also allows us to direct you towards reviewers who
++best understand the different areas you are working on.
++
++When you have made any requested changes, please rebase the commits, verify
++that they still individually look good, then force-push your new branch to
++GitLab. This will update the merge request and notify everyone subscribed to
++your merge request, so they can review it again.
++
++There are also
++[many GitLab CLI clients](https://about.gitlab.com/applications/#cli-clients),
++if you prefer to avoid the web interface. It may be difficult to follow review
++comments without using the web interface though, so we do recommend using this
++to go through the review process, even if you use other clients to track the
++list of available patches.
++
++
++Coding style
++------------
++
++You should follow the style of the file you're editing. In general, we
++try to follow the rules below.
++
++**Note: this file uses spaces due to markdown rendering issues for tabs.
++  Code must be implemented using tabs.**
++
++- indent with tabs, and a tab is always 8 characters wide
++- opening braces are on the same line as the if statement;
++- no braces in an if-body with just one statement;
++- if one of the branches of an if-else condition has braces, then the
++  other branch should also have braces;
++- there is always an empty line between variable declarations and the
++  code;
++
++```c
++static int
++my_function(void)
++{
++        int a = 0;
++
++        if (a)
++                b();
++        else
++                c();
++
++        if (a) {
++                b();
++                c();
++        } else {
++                d();
++        }
++}
++```
++
++- lines should be less than 80 characters wide;
++- when breaking lines with functions calls, the parameters are aligned
++  with the opening parentheses;
++- when assigning a variable with the result of a function call, if the
++  line would be longer we break it around the equal '=' sign if it makes
++  sense;
++
++```c
++        long_variable_name =
++                function_with_a_really_long_name(parameter1, parameter2,
++                                                 parameter3, parameter4);
++
++        x = function_with_a_really_long_name(parameter1, parameter2,
++                                             parameter3, parameter4);
++```
++
++Conduct
++=======
++
++As a freedesktop.org project, Wayland follows the Contributor Covenant,
++found at:
++https://www.freedesktop.org/wiki/CodeOfConduct
++
++Please conduct yourself in a respectful and civilised manner when
++interacting with community members on mailing lists, IRC, or bug
++trackers. The community represents the project as a whole, and abusive
++or bullying behaviour is not tolerated by the project.
++
++
++Licensing
++=========
++
++Wayland is licensed with the intention to be usable anywhere X.org is.
++Originally, X.org was covered under the MIT X11 license, but changed to
++the MIT Expat license.  Similarly, Wayland was covered initially as MIT
++X11 licensed, but changed to the MIT Expat license, following in X.org's
++footsteps.  Other than wording, the two licenses are substantially the
++same, with the exception of a no-advertising clause in X11 not included
++in Expat.
++
++New source code files should specify the MIT Expat license in their
++boilerplate, as part of the copyright statement.
++
++
++Review
++======
++
++All patches, even trivial ones, require at least one positive review
++(Reviewed-by). Additionally, if no Reviewed-by's have been given by
++people with commit access, there needs to be at least one Acked-by from
++someone with commit access. A person with commit access is expected to be
++able to evaluate the patch with respect to the project scope and architecture.
++
++The below review guidelines are intended to be interpreted in spirit, not by
++the letter. There may be circumstances where some guidelines are better
++ignored. We rely very much on the judgement of reviewers and commit rights
++holders.
++
++During review, the following matters should be checked:
++
++- The commit message explains why the change is being made.
++
++- The code fits the project's scope.
++
++- The code license is the same MIT licence the project generally uses.
++
++- Stable ABI or API is not broken.
++
++- Stable ABI or API additions must be justified by actual use cases, not only
++by speculation. They must also be documented, and it is strongly recommended to
++include tests exercising the additions in the test suite.
++
++- The code fits the existing software architecture, e.g. no layering
++violations.
++
++- The code is correct and does not introduce new failures for existing users,
++does not add new corner-case bugs, and does not introduce new compiler
++warnings.
++
++- The patch does what it says in the commit message and changes nothing else.
++
++- The patch is a single logical change. If the commit message addresses
++multiple points, it is a hint that the commit might need splitting up.
++
++- A bug fix should target the underlying root cause instead of hiding symptoms.
++If a complete fix is not practical, partial fixes are acceptable if they come
++with code comments and filed Gitlab issues for the remaining bugs.
++
++- The bug root cause rule applies to external software components as well, e.g.
++do not work around kernel driver issues in userspace.
++
++- The test suite passes.
++
++- The code does not depend on API or ABI which has no working free open source
++implementation.
++
++- The code is not dead or untestable. E.g. if there are no free open source
++software users for it then it is effectively dead code.
++
++- The code is written to be easy to understand, or if code cannot be clear
++enough on its own there are code comments to explain it.
++
++- The code is minimal, i.e. prefer refactor and re-use when possible unless
++clarity suffers.
++
++- The code adheres to the style guidelines.
++
++- In a patch series, every intermediate step adheres to the above guidelines.
++
++
++Commit rights
++=============
++
++Commit rights will be granted to anyone who requests them and fulfills the
++below criteria:
++
++- Submitted some (10 as a rule of thumb) non-trivial (not just simple
++  spelling fixes and whitespace adjustment) patches that have been merged
++  already.
++
++- Are actively participating in public discussions about their work (on the
++  mailing list or IRC). This should not be interpreted as a requirement to
++  review other peoples patches but just make sure that patch submission isn't
++  one-way communication. Cross-review is still highly encouraged.
++
++- Will be regularly contributing further patches. This includes regular
++  contributors to other parts of the open source graphics stack who only
++  do the occasional development in this project.
++
++- Agrees to use their commit rights in accordance with the documented merge
++  criteria, tools, and processes.
++
++To apply for commit rights, create a new issue in gitlab for the respective
++project and give it the "accounts" label.
++
++Committers are encouraged to request their commit rights get removed when they
++no longer contribute to the project. Commit rights will be reinstated when they
++come back to the project.
++
++Maintainers and committers should encourage contributors to request commit
++rights, especially junior contributors tend to underestimate their skills.
++
++
++Stabilising for releases
++========================
++
++A release cycle ends with a stable release which also starts a new cycle and
++lifts any code freezes. Gradual code freezing towards a stable release starts
++with an alpha release. The release stages of a cycle are:
++
++- **Alpha release**:
++    Signified by version number #.#.91.
++    Major features must have landed before this. Major features include
++    invasive code motion and refactoring, high risk changes, and new stable
++    library ABI.
++
++- **Beta release**:
++    Signified by version number #.#.92.
++    Minor features must have landed before this. Minor features include all
++    new features that are not major, low risk changes, clean-ups, and
++    documentation. Stable ABI that was new in the alpha release can be removed
++    before a beta release if necessary.
++
++- **Release candidates (RC)**:
++    Signified by version number #.#.93 and up to #.#.99.
++    Bug fixes that are not release critical must have landed before this.
++    Release critical bug fixes can still be landed after this, but they may
++    call for another RC.
++
++- **Stable release**:
++    Signified by version number #.#.0.
++    Ideally no changes since the last RC.
++
++Mind that version #.#.90 is never released. It is used during development when
++no code freeze is in effect. Stable branches and point releases are not covered
++by the above.
++
++
++[git documentation]: http://git-scm.com/documentation
++[notes on commit messages]: http://who-t.blogspot.de/2009/12/on-commit-messages.html
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..eb25a4e2b3d1582fb47f189c07f96227777c8e09
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,29 @@@
++Copyright © 2008-2012 Kristian Høgsberg
++Copyright © 2010-2012 Intel Corporation
++Copyright © 2011 Benjamin Franzke
++Copyright © 2012 Collabora, Ltd.
++
++Permission is hereby granted, free of charge, to any person obtaining a
++copy of this software and associated documentation files (the "Software"),
++to deal in the Software without restriction, including without limitation
++the rights to use, copy, modify, merge, publish, distribute, sublicense,
++and/or sell copies of the Software, and to permit persons to whom the
++Software is furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice (including the next
++paragraph) shall be included in all copies or substantial portions of the
++Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++DEALINGS IN THE SOFTWARE.
++
++---
++
++The above is the version of the MIT "Expat" License used by X.org:
++
++    http://cgit.freedesktop.org/xorg/xserver/tree/COPYING
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ad06dce68579c16d9a0257be26b7a7ecaccd5d21
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,34 @@@
++What is Wayland?
++
++Wayland is a project to define a protocol for a compositor to talk to
++its clients as well as a library implementation of the protocol.  The
++compositor can be a standalone display server running on Linux kernel
++modesetting and evdev input devices, an X application, or a wayland
++client itself.  The clients can be traditional applications, X servers
++(rootless or fullscreen) or other display servers.
++
++The wayland protocol is essentially only about input handling and
++buffer management.  The compositor receives input events and forwards
++them to the relevant client.  The clients creates buffers and renders
++into them and notifies the compositor when it needs to redraw.  The
++protocol also handles drag and drop, selections, window management and
++other interactions that must go through the compositor.  However, the
++protocol does not handle rendering, which is one of the features that
++makes wayland so simple.  All clients are expected to handle rendering
++themselves, typically through cairo or OpenGL.
++
++The weston compositor is a reference implementation of a wayland
++compositor and the weston repository also includes a few example
++clients.
++
++Building the wayland libraries is fairly simple, aside from libffi,
++they don't have many dependencies:
++
++    $ git clone https://gitlab.freedesktop.org/wayland/wayland
++    $ cd wayland
++    $ meson build/ --prefix=PREFIX
++    $ ninja -C build/ install
++
++where PREFIX is where you want to install the libraries.  See
++https://wayland.freedesktop.org for more complete build instructions
++for wayland, weston, xwayland and various toolkits.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..74e45fbcafc1539c42fe005257103af6c949acfc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,547 @@@
++/*
++ * Copyright © 2012 Philipp Brüschweiler
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/*
++ * This is a small, hacky tool to extract cursors from a .pcf file.
++ * The information about the file format has been gathered from
++ * http://fontforge.org/pcf-format.html
++ */
++
++#include <assert.h>
++#include <fcntl.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#define min(a, b) ((a) < (b) ? (a) : (b))
++#define max(a, b) ((a) > (b) ? (a) : (b))
++
++struct glyph {
++      char *name;
++      int16_t left_bearing, right_bearing, ascent, descent;
++
++      int16_t width, height;
++      int16_t hotx, hoty;
++
++      int32_t data_format;
++      char *data;
++};
++
++static struct {
++      int count;
++      struct glyph *glyphs;
++} extracted_font = {0, NULL};
++
++#define PCF_PROPERTIES                    (1<<0)
++#define PCF_ACCELERATORS          (1<<1)
++#define PCF_METRICS               (1<<2)
++#define PCF_BITMAPS               (1<<3)
++#define PCF_INK_METRICS                   (1<<4)
++#define       PCF_BDF_ENCODINGS           (1<<5)
++#define PCF_SWIDTHS               (1<<6)
++#define PCF_GLYPH_NAMES                   (1<<7)
++#define PCF_BDF_ACCELERATORS      (1<<8)
++
++#define PCF_DEFAULT_FORMAT    0x00000000
++#define PCF_INKBOUNDS         0x00000200
++#define PCF_ACCEL_W_INKBOUNDS 0x00000100
++#define PCF_COMPRESSED_METRICS        0x00000100
++
++#define       PCF_FORMAT_MASK         0xffffff00
++
++struct pcf_header {
++      char header[4];
++      int32_t table_count;
++      struct toc_entry {
++              int32_t type;
++              int32_t format;
++              int32_t size;
++              int32_t offset;
++      } tables[0];
++};
++
++struct compressed_metrics {
++      uint8_t left_sided_bearing;
++      uint8_t right_side_bearing;
++      uint8_t character_width;
++      uint8_t character_ascent;
++      uint8_t character_descent;
++};
++
++struct uncompressed_metrics {
++      int16_t left_sided_bearing;
++      int16_t right_side_bearing;
++      int16_t character_width;
++      int16_t character_ascent;
++      int16_t character_descent;
++      uint16_t character_attributes;
++};
++
++struct metrics {
++      int32_t format;
++      union {
++              struct {
++                      int16_t count;
++                      struct compressed_metrics compressed_metrics[0];
++              } compressed;
++              struct {
++                      int32_t count;
++                      struct uncompressed_metrics uncompressed_metrics[0];
++              } uncompressed;
++      };
++};
++
++struct glyph_names {
++      int32_t format;
++      int32_t glyph_count;
++      int32_t offsets[0];
++};
++
++struct bitmaps {
++      int32_t format;
++      int32_t glyph_count;
++      int32_t offsets[0];
++};
++
++static void
++handle_compressed_metrics(int32_t count, struct compressed_metrics *m)
++{
++      printf("metrics count: %d\n", count);
++      extracted_font.count = count;
++      extracted_font.glyphs = calloc(count, sizeof(struct glyph));
++
++      int i;
++      for (i = 0; i < count; ++i) {
++              struct glyph *glyph = &extracted_font.glyphs[i];
++              glyph->left_bearing =
++                      ((int16_t) m[i].left_sided_bearing) - 0x80;
++              glyph->right_bearing =
++                      ((int16_t) m[i].right_side_bearing) - 0x80;
++              glyph->width = ((int16_t) m[i].character_width) - 0x80;
++              glyph->ascent = ((int16_t) m[i].character_ascent) - 0x80;
++              glyph->descent = ((int16_t) m[i].character_descent) - 0x80;
++
++              /* computed stuff */
++              glyph->height = glyph->ascent + glyph->descent;
++
++              glyph->hotx = -glyph->left_bearing;
++              glyph->hoty = glyph->ascent;
++      }
++}
++
++static void
++handle_metrics(void *metricbuf)
++{
++      struct metrics *metrics = metricbuf;
++      printf("metric format: %x\n", metrics->format);
++
++      if ((metrics->format & PCF_FORMAT_MASK) == PCF_DEFAULT_FORMAT) {
++              printf("todo...\n");
++      } else if ((metrics->format & PCF_FORMAT_MASK) ==
++                 PCF_COMPRESSED_METRICS) {
++              handle_compressed_metrics(
++                  metrics->compressed.count,
++                  &metrics->compressed.compressed_metrics[0]);
++      } else {
++              printf("incompatible format\n");
++              abort();
++      }
++}
++
++static void
++handle_glyph_names(struct glyph_names *names)
++{
++      printf("glyph count %d\n", names->glyph_count);
++
++      if (names->glyph_count != extracted_font.count) {
++              abort();
++      }
++
++      printf("glyph names format %x\n", names->format);
++
++      void *names_start = ((void*) names) + sizeof(struct glyph_names)
++              + (names->glyph_count + 1) * sizeof(int32_t);
++
++      int i;
++      for (i = 0; i < names->glyph_count; ++i) {
++              int32_t start = names->offsets[i];
++              int32_t end = names->offsets[i+1];
++              char *name = names_start + start;
++              extracted_font.glyphs[i].name = calloc(1, end - start + 1);
++              memcpy(extracted_font.glyphs[i].name, name, end - start);
++      }
++}
++
++static void
++handle_bitmaps(struct bitmaps *bitmaps)
++{
++      printf("bitmaps count %d\n", bitmaps->glyph_count);
++
++      if (bitmaps->glyph_count != extracted_font.count) {
++              abort();
++      }
++
++      printf("format %x\n", bitmaps->format);
++
++      if (bitmaps->format != 2) {
++              printf("format not yet supported\n");
++              abort();
++      }
++
++      void *bitmaps_start = ((void*) bitmaps) + sizeof(struct bitmaps)
++              + (bitmaps->glyph_count + 4) * sizeof(int32_t);
++
++      int i;
++      for (i = 0; i < bitmaps->glyph_count; ++i) {
++              int32_t offset = bitmaps->offsets[i];
++              struct glyph *glyph = &extracted_font.glyphs[i];
++              glyph->data_format = bitmaps->format;
++
++              glyph->data = bitmaps_start + offset;
++      }
++}
++
++static void
++handle_pcf(void *fontbuf)
++{
++      struct pcf_header *header = fontbuf;
++      printf("tablecount %d\n", header->table_count);
++
++      int i;
++      for (i = 0; i < header->table_count; ++i) {
++              struct toc_entry *entry = &header->tables[i];
++              printf("type: %d\n", entry->type);
++              if (entry->type == PCF_METRICS) {
++                      handle_metrics(fontbuf + entry->offset);
++              } else if (entry->type == PCF_GLYPH_NAMES) {
++                      handle_glyph_names(fontbuf + entry->offset);
++              } else if (entry->type == PCF_BITMAPS) {
++                      handle_bitmaps(fontbuf + entry->offset);
++              }
++      }
++}
++
++static char
++get_glyph_pixel(struct glyph *glyph, int x, int y)
++{
++      int absx = glyph->hotx + x;
++      int absy = glyph->hoty + y;
++
++      if (absx < 0 || absx >= glyph->width ||
++          absy < 0 || absy >= glyph->height)
++              return 0;
++
++      int stride = (glyph->width + 31) / 32 * 4;
++      unsigned char block = glyph->data[absy * stride + (absx/8)];
++      int idx = absx % 8;
++      return (block >> idx) & 1;
++}
++
++static struct {
++      uint32_t *data;
++      size_t capacity, size;
++} data_buffer;
++
++static void
++init_data_buffer()
++{
++      data_buffer.data = malloc(sizeof(uint32_t) * 10);
++      data_buffer.capacity = 10;
++      data_buffer.size = 0;
++}
++
++static void
++add_pixel(uint32_t pixel)
++{
++      if (data_buffer.size == data_buffer.capacity) {
++              data_buffer.capacity *= 2;
++              data_buffer.data =
++                      realloc(data_buffer.data,
++                              sizeof(uint32_t) * data_buffer.capacity);
++      }
++      data_buffer.data[data_buffer.size++] = pixel;
++}
++
++struct reconstructed_glyph {
++      int32_t width, height;
++      int32_t hotspot_x, hotspot_y;
++      size_t offset;
++      char *name;
++};
++
++static void
++reconstruct_glyph(struct glyph *cursor, struct glyph *mask, char *name,
++                struct reconstructed_glyph *glyph)
++{
++      int minx = min(-cursor->hotx, -mask->hotx);
++      int maxx = max(cursor->right_bearing, mask->right_bearing);
++
++      int miny = min(-cursor->hoty, -mask->hoty);
++      int maxy = max(cursor->height - cursor->hoty,
++                     mask->height - mask->hoty);
++
++      int width = maxx - minx;
++      int height = maxy - miny;
++
++      glyph->name = strdup(name);
++      glyph->width = width;
++      glyph->height = height;
++      glyph->hotspot_x = -minx;
++      glyph->hotspot_y = -miny;
++      glyph->offset = data_buffer.size;
++
++      int x, y;
++      for (y = miny; y < maxy; ++y) {
++              for (x = minx; x < maxx; ++x) {
++                      char alpha = get_glyph_pixel(mask, x, y);
++                      if (alpha) {
++                              char color = get_glyph_pixel(cursor, x, y);
++                              if (color)
++                                      add_pixel(0xff000000);
++                              else
++                                      add_pixel(0xffffffff);
++                      } else {
++                              add_pixel(0);
++                      }
++              }
++      }
++}
++
++/* 
++ * Originally from
++ * http://cgit.freedesktop.org/xorg/lib/libXfont/tree/src/builtins/fonts.c
++ * Changed to the MIT "Expat" style license for Wayland..
++ */
++static const char cursor_licence[] =
++      "/*\n"
++      "* Copyright 1999 SuSE, Inc.\n"
++      "*\n"
++      "* Permission is hereby granted, free of charge, to any person obtaining\n"
++      "* a copy of this software and associated documentation files (the\n"
++      "* \"Software\"), to deal in the Software without restriction, including\n"
++      "* without limitation the rights to use, copy, modify, merge, publish,\n"
++      "* distribute, sublicense, and/or sell copies of the Software, and to\n"
++      "* permit persons to whom the Software is furnished to do so, subject to\n"
++      "* the following conditions:\n"
++      "*\n"
++      "* The above copyright notice and this permission notice (including the\n"
++      "* next paragraph) shall be included in all copies or substantial\n"
++      "* portions of the Software.\n"
++      "*\n"
++      "* THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n"
++      "* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n"
++      "* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n"
++      "* NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n"
++      "* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n"
++      "* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n"
++      "* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n"
++      "* SOFTWARE.\n"
++      "*\n"
++      "* Author:  Keith Packard, SuSE, Inc.\n"
++      "*/\n";
++
++static void
++write_output_file(struct reconstructed_glyph *glyphs, int n)
++{
++      int i, j, counter, size;
++      FILE *file = fopen("cursor-data.h", "w");
++      uint32_t *data;
++
++      fprintf(file, "%s\n", cursor_licence);
++
++      fprintf(file, "static uint32_t cursor_data[] = {\n\t");
++
++      counter = 0;
++      for (i = 0; i < n; ++i) {
++              data = data_buffer.data + glyphs[i].offset;
++              size = glyphs[i].width * glyphs[i].height;
++
++              for (j = 0; j < size; ++j) {
++                      fprintf(file, "0x%08x, ", data[j]);
++                      if (++counter % 6 == 0)
++                              fprintf(file, "\n\t");
++              }
++      }
++      fprintf(file, "\n};\n\n");
++
++      fprintf(file,
++              "static struct {\n"
++              "\tchar *name;\n"
++              "\tint width, height;\n"
++              "\tint hotspot_x, hotspot_y;\n"
++              "\tsize_t offset;\n"
++              "} cursor_metadata[] = {\n");
++
++      for (i = 0; i < n; ++i)
++              fprintf(file, "\t{ \"%s\", %d, %d, %d, %d, %zu },\n",
++                      glyphs[i].name,
++                      glyphs[i].width, glyphs[i].height,
++                      glyphs[i].hotspot_x, glyphs[i].hotspot_y,
++                      glyphs[i].offset);
++
++      fprintf(file, "};");
++
++      fclose(file);
++}
++
++struct glyph *
++find_mask_glyph(char *name)
++{
++      const char mask[] = "_mask";
++      const int masklen = strlen(mask);
++
++      int len = strlen(name);
++      int i;
++      for (i = 0; i < extracted_font.count; ++i) {
++              struct glyph *g = &extracted_font.glyphs[i];
++              int l2 = strlen(g->name);
++              if ((l2 == len + masklen) &&
++                  (memcmp(g->name, name, len) == 0) &&
++                  (memcmp(g->name + len, mask, masklen) == 0)) {
++                      return g;
++              }
++      }
++      return NULL;
++}
++
++static void
++output_all_cursors()
++{
++      int i, j;
++      struct reconstructed_glyph *glyphs =
++              malloc(sizeof(struct reconstructed_glyph) *
++                     extracted_font.count/2);
++      j = 0;
++
++      for (i = 0; i < extracted_font.count; ++i) {
++              struct glyph *g = &extracted_font.glyphs[i];
++              if (strstr(g->name, "_mask"))
++                      continue;
++
++              struct glyph *mask = find_mask_glyph(g->name);
++
++              reconstruct_glyph(g, mask, g->name, &glyphs[j]);
++              j++;
++      }
++
++      write_output_file(glyphs, extracted_font.count/2);
++}
++
++static void
++find_cursor_and_mask(const char *name,
++                   struct glyph **cursor,
++                   struct glyph **mask)
++{
++      int i;
++      char mask_name[100];
++      sprintf(mask_name, "%s_mask", name);
++
++      *cursor = *mask = NULL;
++
++      for (i = 0; i < extracted_font.count && (!*mask || !*cursor); ++i) {
++              struct glyph *g = &extracted_font.glyphs[i];
++              if (!strcmp(name, g->name))
++                      *cursor = g;
++              else if (!strcmp(mask_name, g->name))
++                      *mask = g;
++      }
++}
++
++static struct {
++      char *target_name, *source_name;
++} interesting_cursors[] = {
++      { "bottom_left_corner", "bottom_left_corner" },
++      { "bottom_right_corner", "bottom_right_corner" },
++      { "bottom_side", "bottom_side" },
++      { "grabbing", "fleur" },
++      { "left_ptr", "left_ptr" },
++      { "left_side", "left_side" },
++      { "right_side", "right_side" },
++      { "top_left_corner", "top_left_corner" },
++      { "top_right_corner", "top_right_corner" },
++      { "top_side", "top_side" },
++      { "xterm", "xterm" },
++      { "hand1", "hand1" },
++      { "watch", "watch" }
++};
++
++static void
++output_interesting_cursors()
++{
++      int i;
++      int n = sizeof(interesting_cursors) / sizeof(interesting_cursors[0]);
++      struct reconstructed_glyph *glyphs =
++              malloc(n * sizeof(*glyphs));
++
++      if (!glyphs) {
++              printf("reconstructed_glyph malloc failed\n");
++              abort();
++      }
++
++      for (i = 0; i < n; ++i) {
++              struct glyph *cursor, *mask;
++              find_cursor_and_mask(interesting_cursors[i].source_name,
++                                   &cursor, &mask);
++              if (!cursor) {
++                      printf("no cursor for %s\n",
++                             interesting_cursors[i].source_name);
++                      abort();
++              }
++              if (!mask) {
++                      printf("no mask for %s\n",
++                             interesting_cursors[i].source_name);
++                      abort();
++              }
++              reconstruct_glyph(cursor, mask,
++                                interesting_cursors[i].target_name,
++                                &glyphs[i]);
++      }
++
++      write_output_file(glyphs, n);
++}
++
++int main()
++{
++      const char filename[] = "cursor.pcf";
++
++      int fd = open(filename, O_RDONLY);
++      struct stat filestat;
++
++      fstat(fd, &filestat);
++
++      void *fontbuf = mmap(NULL, filestat.st_size, PROT_READ,
++                           MAP_PRIVATE, fd, 0);
++
++      handle_pcf(fontbuf);
++
++      init_data_buffer();
++
++      //output_all_cursors();
++      output_interesting_cursors();
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..dd7a80af594809a032144fe53a1a783164991aa7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,554 @@@
++/*
++* Copyright 1999 SuSE, Inc.
++*
++* Permission is hereby granted, free of charge, to any person obtaining
++* a copy of this software and associated documentation files (the
++* "Software"), to deal in the Software without restriction, including
++* without limitation the rights to use, copy, modify, merge, publish,
++* distribute, sublicense, and/or sell copies of the Software, and to
++* permit persons to whom the Software is furnished to do so, subject to
++* the following conditions:
++*
++* The above copyright notice and this permission notice (including the
++* next paragraph) shall be included in all copies or substantial
++* portions of the Software.
++*
++* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++* NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++* SOFTWARE.
++*
++* Author:  Keith Packard, SuSE, Inc.
++*/
++
++#include <stdint.h>
++
++static uint32_t cursor_data[] = {
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
++      0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0x00000000, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0x00000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0x00000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0xff000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xff000000, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xff000000, 0xff000000, 0xffffffff, 0xffffffff, 0xffffffff,
++      0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffffffff,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffffffff, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000, 0xffffffff, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xffffffff,
++      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
++      0xffffffff, 0xff000000, 0xff000000, 0xff000000, 0xff000000, 0xff000000,
++      0xff000000, 0xff000000, 0xff000000, 0xffffffff, 0x00000000, 0x00000000,
++      0x00000000, 0x00000000,
++};
++
++static struct cursor_metadata {
++      char *name;
++      int width, height;
++      int hotspot_x, hotspot_y;
++      size_t offset;
++} cursor_metadata[] = {
++      { "bottom_left_corner", 16, 16, 1, 14, 0 },
++      { "bottom_right_corner", 16, 16, 14, 14, 256 },
++      { "bottom_side", 15, 16, 7, 14, 512 },
++      { "grabbing", 16, 16, 8, 8, 752 },
++      { "left_ptr", 10, 16, 1, 1, 1008 },
++      { "left_side", 16, 15, 1, 7, 1168 },
++      { "right_side", 16, 15, 14, 7, 1408 },
++      { "top_left_corner", 16, 16, 1, 1, 1648 },
++      { "top_right_corner", 16, 16, 14, 1, 1904 },
++      { "top_side", 15, 16, 7, 1, 2160 },
++      { "xterm", 9, 16, 4, 8, 2400 },
++      { "hand1", 13, 16, 12, 0, 2544 },
++      { "watch", 16, 16, 15, 9, 2752 },
++};
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..812fcc54fdf1ad92f7016e69fe6c2dd9f7437b62
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f7d82e4ee0872b449b2411e273b589ae7db060f9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,47 @@@
++icondir = get_option('icon_directory')
++if icondir == ''
++      icondir = join_paths(get_option('prefix'), get_option('datadir'), 'icons')
++endif
++
++if wayland_version[0] != '1'
++      # The versioning used for the shared libraries assumes that the major
++      # version of Wayland as a whole will increase to 2 if and only if there
++      # is an ABI break, at which point we should probably bump the SONAME of
++      # all libraries to .so.2. For more details see
++      # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177
++      error('We probably need to bump the SONAME of libwayland-cursor')
++endif
++
++wayland_cursor = library(
++      'wayland-cursor',
++      sources: [
++              'wayland-cursor.c',
++              'os-compatibility.c',
++              'xcursor.c',
++      ],
++      # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++      # libwayland-cursor.so.0.x.y.
++      version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++      dependencies: [ wayland_client_dep ],
++      c_args: [ '-DICONDIR="@0@"'.format(icondir) ],
++      install: true,
++)
++
++install_headers('wayland-cursor.h')
++
++pkgconfig.generate(
++      name: 'Wayland Cursor',
++      description: 'Wayland cursor helper library',
++      version: meson.project_version(),
++      libraries: wayland_cursor,
++      filebase: 'wayland-cursor',
++)
++
++wayland_cursor_dep = declare_dependency(
++      link_with: wayland_cursor,
++      include_directories: [ root_inc, include_directories('.') ],
++)
++
++if meson.version().version_compare('>= 0.54.0')
++      meson.override_dependency('wayland-cursor', wayland_cursor_dep)
++endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f2445ced9cabed23b030776efe8ed02257d6652e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,203 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include "config.h"
++
++#include <sys/types.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <signal.h>
++#include <string.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++#ifdef HAVE_MEMFD_CREATE
++#include <sys/mman.h>
++#endif
++
++#include "os-compatibility.h"
++
++#ifndef HAVE_MKOSTEMP
++static int
++set_cloexec_or_close(int fd)
++{
++      long flags;
++
++      if (fd == -1)
++              return -1;
++
++      flags = fcntl(fd, F_GETFD);
++      if (flags == -1)
++              goto err;
++
++      if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
++              goto err;
++
++      return fd;
++
++err:
++      close(fd);
++      return -1;
++}
++#endif
++
++static int
++create_tmpfile_cloexec(char *tmpname)
++{
++      int fd;
++
++#ifdef HAVE_MKOSTEMP
++      fd = mkostemp(tmpname, O_CLOEXEC);
++      if (fd >= 0)
++              unlink(tmpname);
++#else
++      fd = mkstemp(tmpname);
++      if (fd >= 0) {
++              fd = set_cloexec_or_close(fd);
++              unlink(tmpname);
++      }
++#endif
++
++      return fd;
++}
++
++/*
++ * Create a new, unique, anonymous file of the given size, and
++ * return the file descriptor for it. The file descriptor is set
++ * CLOEXEC. The file is immediately suitable for mmap()'ing
++ * the given size at offset zero.
++ *
++ * The file should not have a permanent backing store like a disk,
++ * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
++ *
++ * The file name is deleted from the file system.
++ *
++ * The file is suitable for buffer sharing between processes by
++ * transmitting the file descriptor over Unix sockets using the
++ * SCM_RIGHTS methods.
++ *
++ * If the C library implements posix_fallocate(), it is used to
++ * guarantee that disk space is available for the file at the
++ * given size. If disk space is insufficient, errno is set to ENOSPC.
++ * If posix_fallocate() is not supported, program may receive
++ * SIGBUS on accessing mmap()'ed file contents instead.
++ *
++ * If the C library implements memfd_create(), it is used to create the
++ * file purely in memory, without any backing file name on the file
++ * system, and then sealing off the possibility of shrinking it.  This
++ * can then be checked before accessing mmap()'ed file contents, to
++ * make sure SIGBUS can't happen.  It also avoids requiring
++ * XDG_RUNTIME_DIR.
++ */
++int
++os_create_anonymous_file(off_t size)
++{
++      static const char template[] = "/wayland-cursor-shared-XXXXXX";
++      const char *path;
++      char *name;
++      size_t name_size;
++      int fd;
++
++#ifdef HAVE_MEMFD_CREATE
++      fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
++      if (fd >= 0) {
++              /* We can add this seal before calling posix_fallocate(), as
++               * the file is currently zero-sized anyway.
++               *
++               * There is also no need to check for the return value, we
++               * couldn't do anything with it anyway.
++               */
++              fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
++      } else
++#endif
++      {
++              path = getenv("XDG_RUNTIME_DIR");
++              if (!path || path[0] != '/') {
++                      errno = ENOENT;
++                      return -1;
++              }
++
++              name_size = strlen(path) + sizeof(template);
++              name = malloc(name_size);
++              if (!name)
++                      return -1;
++
++              snprintf(name, name_size, "%s%s", path, template);
++
++              fd = create_tmpfile_cloexec(name);
++
++              free(name);
++
++              if (fd < 0)
++                      return -1;
++      }
++
++      if (os_resize_anonymous_file(fd, size) < 0) {
++              close(fd);
++              return -1;
++      }
++
++      return fd;
++}
++
++int
++os_resize_anonymous_file(int fd, off_t size)
++{
++#ifdef HAVE_POSIX_FALLOCATE
++      sigset_t mask;
++      sigset_t old_mask;
++
++      /*
++       * posix_fallocate() might be interrupted, so we need to check
++       * for EINTR and retry in that case.
++       * However, in the presence of an alarm, the interrupt may trigger
++       * repeatedly and prevent a large posix_fallocate() to ever complete
++       * successfully, so we need to first block SIGALRM to prevent
++       * this.
++       */
++      sigemptyset(&mask);
++      sigaddset(&mask, SIGALRM);
++      sigprocmask(SIG_BLOCK, &mask, &old_mask);
++      /*
++       * Filesystems that do not support fallocate will return EINVAL or
++       * EOPNOTSUPP. In this case we need to fall back to ftruncate
++       */
++      do {
++              errno = posix_fallocate(fd, 0, size);
++      } while (errno == EINTR);
++      sigprocmask(SIG_SETMASK, &old_mask, NULL);
++      if (errno == 0)
++              return 0;
++      else if (errno != EINVAL && errno != EOPNOTSUPP)
++              return -1;
++#endif
++      if (ftruncate(fd, size) < 0)
++              return -1;
++
++      return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fdfeb78b143309915956de3ea92303776a3743b0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,37 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef OS_COMPATIBILITY_H
++#define OS_COMPATIBILITY_H
++
++#include <sys/types.h>
++
++int
++os_create_anonymous_file(off_t size);
++
++int
++os_resize_anonymous_file(int fd, off_t size);
++
++#endif /* OS_COMPATIBILITY_H */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3518aa44f8d820b2f2db0da34235ba94773e5cbc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,516 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++#include "xcursor.h"
++#include "wayland-cursor.h"
++#include "wayland-client.h"
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/mman.h>
++#include <fcntl.h>
++#include <errno.h>
++
++#include "os-compatibility.h"
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++struct shm_pool {
++      struct wl_shm_pool *pool;
++      int fd;
++      unsigned int size;
++      unsigned int used;
++      char *data;
++};
++
++static struct shm_pool *
++shm_pool_create(struct wl_shm *shm, int size)
++{
++      struct shm_pool *pool;
++
++      pool = malloc(sizeof *pool);
++      if (!pool)
++              return NULL;
++
++      pool->fd = os_create_anonymous_file(size);
++      if (pool->fd < 0)
++              goto err_free;
++
++      pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
++                        pool->fd, 0);
++
++      if (pool->data == MAP_FAILED)
++              goto err_close;
++
++      pool->pool = wl_shm_create_pool(shm, pool->fd, size);
++      pool->size = size;
++      pool->used = 0;
++
++      return pool;
++
++err_close:
++      close(pool->fd);
++err_free:
++      free(pool);
++      return NULL;
++}
++
++static int
++shm_pool_resize(struct shm_pool *pool, int size)
++{
++      if (os_resize_anonymous_file(pool->fd, size) < 0)
++              return 0;
++
++      wl_shm_pool_resize(pool->pool, size);
++
++      munmap(pool->data, pool->size);
++
++      pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
++                        pool->fd, 0);
++      if (pool->data == MAP_FAILED)
++              return 0;
++      pool->size = size;
++
++      return 1;
++}
++
++static int
++shm_pool_allocate(struct shm_pool *pool, int size)
++{
++      int offset;
++
++      if (pool->used + size > pool->size)
++              if (!shm_pool_resize(pool, 2 * pool->size + size))
++                      return -1;
++
++      offset = pool->used;
++      pool->used += size;
++
++      return offset;
++}
++
++static void
++shm_pool_destroy(struct shm_pool *pool)
++{
++      munmap(pool->data, pool->size);
++      wl_shm_pool_destroy(pool->pool);
++      close(pool->fd);
++      free(pool);
++}
++
++
++struct wl_cursor_theme {
++      unsigned int cursor_count;
++      struct wl_cursor **cursors;
++      struct wl_shm *shm;
++      struct shm_pool *pool;
++      int size;
++};
++
++struct cursor_image {
++      struct wl_cursor_image image;
++      struct wl_cursor_theme *theme;
++      struct wl_buffer *buffer;
++      int offset; /* data offset of this image in the shm pool */
++};
++
++struct cursor {
++      struct wl_cursor cursor;
++      uint32_t total_delay; /* length of the animation in ms */
++};
++
++/** Get an shm buffer for a cursor image
++ *
++ * \param image The cursor image
++ * \return An shm buffer for the cursor image. The user should not destroy
++ * the returned buffer.
++ */
++WL_EXPORT struct wl_buffer *
++wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
++{
++      struct cursor_image *image = (struct cursor_image *) _img;
++      struct wl_cursor_theme *theme = image->theme;
++
++      if (!image->buffer) {
++              image->buffer =
++                      wl_shm_pool_create_buffer(theme->pool->pool,
++                                                image->offset,
++                                                _img->width, _img->height,
++                                                _img->width * 4,
++                                                WL_SHM_FORMAT_ARGB8888);
++      };
++
++      return image->buffer;
++}
++
++static void
++wl_cursor_image_destroy(struct wl_cursor_image *_img)
++{
++      struct cursor_image *image = (struct cursor_image *) _img;
++
++      if (image->buffer)
++              wl_buffer_destroy(image->buffer);
++
++      free(image);
++}
++
++static void
++wl_cursor_destroy(struct wl_cursor *cursor)
++{
++      unsigned int i;
++
++      for (i = 0; i < cursor->image_count; i++)
++              wl_cursor_image_destroy(cursor->images[i]);
++
++      free(cursor->images);
++      free(cursor->name);
++      free(cursor);
++}
++
++#include "cursor-data.h"
++
++static struct wl_cursor *
++wl_cursor_create_from_data(struct cursor_metadata *metadata,
++                         struct wl_cursor_theme *theme)
++{
++      struct cursor *cursor;
++      struct cursor_image *image;
++      int size;
++
++      cursor = malloc(sizeof *cursor);
++      if (!cursor)
++              return NULL;
++
++      cursor->cursor.image_count = 1;
++      cursor->cursor.images = malloc(sizeof *cursor->cursor.images);
++      if (!cursor->cursor.images)
++              goto err_free_cursor;
++
++      cursor->cursor.name = strdup(metadata->name);
++      cursor->total_delay = 0;
++
++      image = malloc(sizeof *image);
++      if (!image)
++              goto err_free_images;
++
++      cursor->cursor.images[0] = (struct wl_cursor_image *) image;
++      image->theme = theme;
++      image->buffer = NULL;
++      image->image.width = metadata->width;
++      image->image.height = metadata->height;
++      image->image.hotspot_x = metadata->hotspot_x;
++      image->image.hotspot_y = metadata->hotspot_y;
++      image->image.delay = 0;
++
++      size = metadata->width * metadata->height * sizeof(uint32_t);
++      image->offset = shm_pool_allocate(theme->pool, size);
++
++      if (image->offset < 0)
++              goto err_free_image;
++
++      memcpy(theme->pool->data + image->offset,
++             cursor_data + metadata->offset, size);
++
++      return &cursor->cursor;
++
++err_free_image:
++      free(image);
++
++err_free_images:
++      free(cursor->cursor.name);
++      free(cursor->cursor.images);
++
++err_free_cursor:
++      free(cursor);
++      return NULL;
++}
++
++static void
++load_fallback_theme(struct wl_cursor_theme *theme)
++{
++      uint32_t i;
++
++      theme->cursor_count = ARRAY_LENGTH(cursor_metadata);
++      theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors));
++
++      if (theme->cursors == NULL) {
++              theme->cursor_count = 0;
++              return;
++      }
++
++      for (i = 0; i < theme->cursor_count; ++i) {
++              theme->cursors[i] =
++                      wl_cursor_create_from_data(&cursor_metadata[i], theme);
++
++              if (theme->cursors[i] == NULL)
++                      break;
++      }
++      theme->cursor_count = i;
++}
++
++static struct wl_cursor *
++wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
++                                   struct wl_cursor_theme *theme)
++{
++      struct cursor *cursor;
++      struct cursor_image *image;
++      int i, size;
++
++      cursor = malloc(sizeof *cursor);
++      if (!cursor)
++              return NULL;
++
++      cursor->cursor.images =
++              malloc(images->nimage * sizeof cursor->cursor.images[0]);
++      if (!cursor->cursor.images) {
++              free(cursor);
++              return NULL;
++      }
++
++      cursor->cursor.name = strdup(images->name);
++      cursor->total_delay = 0;
++
++      for (i = 0; i < images->nimage; i++) {
++              image = malloc(sizeof *image);
++              if (image == NULL)
++                      break;
++
++              image->theme = theme;
++              image->buffer = NULL;
++
++              image->image.width = images->images[i]->width;
++              image->image.height = images->images[i]->height;
++              image->image.hotspot_x = images->images[i]->xhot;
++              image->image.hotspot_y = images->images[i]->yhot;
++              image->image.delay = images->images[i]->delay;
++
++              size = image->image.width * image->image.height * 4;
++              image->offset = shm_pool_allocate(theme->pool, size);
++              if (image->offset < 0) {
++                      free(image);
++                      break;
++              }
++
++              /* copy pixels to shm pool */
++              memcpy(theme->pool->data + image->offset,
++                     images->images[i]->pixels, size);
++              cursor->total_delay += image->image.delay;
++              cursor->cursor.images[i] = (struct wl_cursor_image *) image;
++      }
++      cursor->cursor.image_count = i;
++
++      if (cursor->cursor.image_count == 0) {
++              free(cursor->cursor.name);
++              free(cursor->cursor.images);
++              free(cursor);
++              return NULL;
++      }
++
++      return &cursor->cursor;
++}
++
++static void
++load_callback(struct xcursor_images *images, void *data)
++{
++      struct wl_cursor_theme *theme = data;
++      struct wl_cursor *cursor;
++
++      if (wl_cursor_theme_get_cursor(theme, images->name)) {
++              xcursor_images_destroy(images);
++              return;
++      }
++
++      cursor = wl_cursor_create_from_xcursor_images(images, theme);
++
++      if (cursor) {
++              theme->cursor_count++;
++              theme->cursors =
++                      realloc(theme->cursors,
++                              theme->cursor_count * sizeof theme->cursors[0]);
++
++              if (theme->cursors == NULL) {
++                      theme->cursor_count--;
++                      free(cursor);
++              } else {
++                      theme->cursors[theme->cursor_count - 1] = cursor;
++              }
++      }
++
++      xcursor_images_destroy(images);
++}
++
++/** Load a cursor theme to memory shared with the compositor
++ *
++ * \param name The name of the cursor theme to load. If %NULL, the default
++ * theme will be loaded.
++ * \param size Desired size of the cursor images.
++ * \param shm The compositor's shm interface.
++ *
++ * \return An object representing the theme that should be destroyed with
++ * wl_cursor_theme_destroy() or %NULL on error. If no theme with the given
++ * name exists, a default theme will be loaded.
++ */
++WL_EXPORT struct wl_cursor_theme *
++wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
++{
++      struct wl_cursor_theme *theme;
++
++      theme = malloc(sizeof *theme);
++      if (!theme)
++              return NULL;
++
++      if (!name)
++              name = "default";
++
++      theme->size = size;
++      theme->cursor_count = 0;
++      theme->cursors = NULL;
++
++      theme->pool = shm_pool_create(shm, size * size * 4);
++      if (!theme->pool)
++              goto out_error_pool;
++
++      xcursor_load_theme(name, size, load_callback, theme);
++
++      if (theme->cursor_count == 0)
++              xcursor_load_theme(NULL, size, load_callback, theme);
++
++      if (theme->cursor_count == 0)
++              load_fallback_theme(theme);
++
++      return theme;
++
++out_error_pool:
++      free(theme);
++      return NULL;
++}
++
++/** Destroys a cursor theme object
++ *
++ * \param theme The cursor theme to be destroyed
++ */
++WL_EXPORT void
++wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
++{
++      unsigned int i;
++
++      for (i = 0; i < theme->cursor_count; i++)
++              wl_cursor_destroy(theme->cursors[i]);
++
++      shm_pool_destroy(theme->pool);
++
++      free(theme->cursors);
++      free(theme);
++}
++
++/** Get the cursor for a given name from a cursor theme
++ *
++ * \param theme The cursor theme
++ * \param name Name of the desired cursor
++ * \return The theme's cursor of the given name or %NULL if there is no
++ * such cursor
++ */
++WL_EXPORT struct wl_cursor *
++wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
++                         const char *name)
++{
++      unsigned int i;
++
++      for (i = 0; i < theme->cursor_count; i++) {
++              if (strcmp(name, theme->cursors[i]->name) == 0)
++                      return theme->cursors[i];
++      }
++
++      return NULL;
++}
++
++/** Find the frame for a given elapsed time in a cursor animation
++ *  as well as the time left until next cursor change.
++ *
++ * \param cursor The cursor
++ * \param time Elapsed time in ms since the beginning of the animation
++ * \param duration pointer to uint32_t to store time left for this image or
++ *                 zero if the cursor won't change.
++ *
++ * \return The index of the image that should be displayed for the
++ * given time in the cursor animation.
++ */
++WL_EXPORT int
++wl_cursor_frame_and_duration(struct wl_cursor *_cursor, uint32_t time,
++                           uint32_t *duration)
++{
++      struct cursor *cursor = (struct cursor *) _cursor;
++      uint32_t t;
++      int i;
++
++      if (cursor->cursor.image_count == 1 || cursor->total_delay == 0) {
++              if (duration)
++                      *duration = 0;
++              return 0;
++      }
++
++      i = 0;
++      t = time % cursor->total_delay;
++
++      /* If there is a 0 delay in the image set then this
++       * loop breaks on it and we display that cursor until
++       * time % cursor->total_delay wraps again.
++       * Since a 0 delay is silly, and we've never actually
++       * seen one in a cursor file, we haven't bothered to
++       * "fix" this.
++       */
++      while (t - cursor->cursor.images[i]->delay < t)
++              t -= cursor->cursor.images[i++]->delay;
++
++      if (!duration)
++              return i;
++
++      /* Make sure we don't accidentally tell the caller this is
++       * a static cursor image.
++       */
++      if (t >= cursor->cursor.images[i]->delay)
++              *duration = 1;
++      else
++              *duration = cursor->cursor.images[i]->delay - t;
++
++      return i;
++}
++
++/** Find the frame for a given elapsed time in a cursor animation
++ *
++ * \param cursor The cursor
++ * \param time Elapsed time in ms since the beginning of the animation
++ *
++ * \return The index of the image that should be displayed for the
++ * given time in the cursor animation.
++ */
++WL_EXPORT int
++wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time)
++{
++      return wl_cursor_frame_and_duration(_cursor, time, NULL);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..915a1100c108e98169087364265bee6126d4b3fd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,96 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_CURSOR_H
++#define WAYLAND_CURSOR_H
++
++#include <stdint.h>
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++struct wl_cursor_theme;
++struct wl_buffer;
++struct wl_shm;
++
++/** A still image part of a cursor
++ *
++ * Use `wl_cursor_image_get_buffer()` to get the corresponding `struct
++ * wl_buffer` to attach to your `struct wl_surface`. */
++struct wl_cursor_image {
++      /** Actual width */
++      uint32_t width;
++
++      /** Actual height */
++      uint32_t height;
++
++      /** Hot spot x (must be inside image) */
++      uint32_t hotspot_x;
++
++      /** Hot spot y (must be inside image) */
++      uint32_t hotspot_y;
++
++      /** Animation delay to next frame (ms) */
++      uint32_t delay;
++};
++
++/** A cursor, as returned by `wl_cursor_theme_get_cursor()` */
++struct wl_cursor {
++      /** How many images there are in this cursor’s animation */
++      unsigned int image_count;
++
++      /** The array of still images composing this animation */
++      struct wl_cursor_image **images;
++
++      /** The name of this cursor */
++      char *name;
++};
++
++struct wl_cursor_theme *
++wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm);
++
++void
++wl_cursor_theme_destroy(struct wl_cursor_theme *theme);
++
++struct wl_cursor *
++wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
++                         const char *name);
++
++struct wl_buffer *
++wl_cursor_image_get_buffer(struct wl_cursor_image *image);
++
++int
++wl_cursor_frame(struct wl_cursor *cursor, uint32_t time);
++
++int
++wl_cursor_frame_and_duration(struct wl_cursor *cursor, uint32_t time,
++                           uint32_t *duration);
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..43a5292c81128f3331ca6cdb5496d2fa566416b5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,783 @@@
++/*
++ * Copyright © 2002 Keith Packard
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include "xcursor.h"
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <dirent.h>
++
++/*
++ * Cursor files start with a header.  The header
++ * contains a magic number, a version number and a
++ * table of contents which has type and offset information
++ * for the remaining tables in the file.
++ *
++ * File minor versions increment for compatible changes
++ * File major versions increment for incompatible changes (never, we hope)
++ *
++ * Chunks of the same type are always upward compatible.  Incompatible
++ * changes are made with new chunk types; the old data can remain under
++ * the old type.  Upward compatible changes can add header data as the
++ * header lengths are specified in the file.
++ *
++ *  File:
++ *    FileHeader
++ *    LISTofChunk
++ *
++ *  FileHeader:
++ *    CARD32          magic       magic number
++ *    CARD32          header      bytes in file header
++ *    CARD32          version     file version
++ *    CARD32          ntoc        number of toc entries
++ *    LISTofFileToc   toc         table of contents
++ *
++ *  FileToc:
++ *    CARD32          type        entry type
++ *    CARD32          subtype     entry subtype (size for images)
++ *    CARD32          position    absolute file position
++ */
++
++#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */
++
++/*
++ * This version number is stored in cursor files; changes to the
++ * file format require updating this version number
++ */
++#define XCURSOR_FILE_MAJOR 1
++#define XCURSOR_FILE_MINOR 0
++#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR))
++#define XCURSOR_FILE_HEADER_LEN (4 * 4)
++#define XCURSOR_FILE_TOC_LEN (3 * 4)
++
++struct xcursor_file_toc {
++      uint32_t type; /* chunk type */
++      uint32_t subtype; /* subtype (size for images) */
++      uint32_t position; /* absolute position in file */
++};
++
++struct xcursor_file_header {
++      uint32_t magic; /* magic number */
++      uint32_t header; /* byte length of header */
++      uint32_t version; /* file version number */
++      uint32_t ntoc; /* number of toc entries */
++      struct xcursor_file_toc *tocs; /* table of contents */
++};
++
++/*
++ * The rest of the file is a list of chunks, each tagged by type
++ * and version.
++ *
++ *  Chunk:
++ *    ChunkHeader
++ *    <extra type-specific header fields>
++ *    <type-specific data>
++ *
++ *  ChunkHeader:
++ *    CARD32      header      bytes in chunk header + type header
++ *    CARD32      type        chunk type
++ *    CARD32      subtype     chunk subtype
++ *    CARD32      version     chunk type version
++ */
++
++#define XCURSOR_CHUNK_HEADER_LEN (4 * 4)
++
++struct xcursor_chunk_header {
++      uint32_t header; /* bytes in chunk header */
++      uint32_t type; /* chunk type */
++      uint32_t subtype; /* chunk subtype (size for images) */
++      uint32_t version; /* version of this type */
++};
++
++/*
++ * Each cursor image occupies a separate image chunk.
++ * The length of the image header follows the chunk header
++ * so that future versions can extend the header without
++ * breaking older applications
++ *
++ *  Image:
++ *    ChunkHeader     header  chunk header
++ *    CARD32          width   actual width
++ *    CARD32          height  actual height
++ *    CARD32          xhot    hot spot x
++ *    CARD32          yhot    hot spot y
++ *    CARD32          delay   animation delay
++ *    LISTofCARD32    pixels  ARGB pixels
++ */
++
++#define XCURSOR_IMAGE_TYPE 0xfffd0002
++#define XCURSOR_IMAGE_VERSION 1
++#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4))
++#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */
++
++/*
++ * From libXcursor/src/file.c
++ */
++
++static struct xcursor_image *
++xcursor_image_create(int width, int height)
++{
++      struct xcursor_image *image;
++
++      if (width < 0 || height < 0)
++              return NULL;
++      if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE)
++              return NULL;
++
++      image = malloc(sizeof(struct xcursor_image) +
++                     width * height * sizeof(uint32_t));
++      if (!image)
++              return NULL;
++      image->version = XCURSOR_IMAGE_VERSION;
++      image->pixels = (uint32_t *) (image + 1);
++      image->size = width > height ? width : height;
++      image->width = width;
++      image->height = height;
++      image->delay = 0;
++      return image;
++}
++
++static void
++xcursor_image_destroy(struct xcursor_image *image)
++{
++      free(image);
++}
++
++static struct xcursor_images *
++xcursor_images_create(int size)
++{
++      struct xcursor_images *images;
++
++      images = malloc(sizeof(struct xcursor_images) +
++                      size * sizeof(struct xcursor_image *));
++      if (!images)
++              return NULL;
++      images->nimage = 0;
++      images->images = (struct xcursor_image **) (images + 1);
++      images->name = NULL;
++      return images;
++}
++
++void
++xcursor_images_destroy(struct xcursor_images *images)
++{
++      int n;
++
++      if (!images)
++              return;
++
++      for (n = 0; n < images->nimage; n++)
++              xcursor_image_destroy(images->images[n]);
++      free(images->name);
++      free(images);
++}
++
++static bool
++xcursor_read_uint(FILE *file, uint32_t *u)
++{
++      unsigned char bytes[4];
++
++      if (!file || !u)
++              return false;
++
++      if (fread(bytes, 1, 4, file) != 4)
++              return false;
++
++      *u = ((uint32_t)(bytes[0]) << 0) |
++               ((uint32_t)(bytes[1]) << 8) |
++               ((uint32_t)(bytes[2]) << 16) |
++               ((uint32_t)(bytes[3]) << 24);
++      return true;
++}
++
++static void
++xcursor_file_header_destroy(struct xcursor_file_header *file_header)
++{
++      free(file_header);
++}
++
++static struct xcursor_file_header *
++xcursor_file_header_create(uint32_t ntoc)
++{
++      struct xcursor_file_header *file_header;
++
++      if (ntoc > 0x10000)
++              return NULL;
++      file_header = malloc(sizeof(struct xcursor_file_header) +
++                          ntoc * sizeof(struct xcursor_file_toc));
++      if (!file_header)
++              return NULL;
++      file_header->magic = XCURSOR_MAGIC;
++      file_header->header = XCURSOR_FILE_HEADER_LEN;
++      file_header->version = XCURSOR_FILE_VERSION;
++      file_header->ntoc = ntoc;
++      file_header->tocs = (struct xcursor_file_toc *) (file_header + 1);
++      return file_header;
++}
++
++static struct xcursor_file_header *
++xcursor_read_file_header(FILE *file)
++{
++      struct xcursor_file_header head, *file_header;
++      uint32_t skip;
++      unsigned int n;
++
++      if (!file)
++              return NULL;
++
++      if (!xcursor_read_uint(file, &head.magic))
++              return NULL;
++      if (head.magic != XCURSOR_MAGIC)
++              return NULL;
++      if (!xcursor_read_uint(file, &head.header))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.version))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.ntoc))
++              return NULL;
++      skip = head.header - XCURSOR_FILE_HEADER_LEN;
++      if (skip)
++              if (fseek(file, skip, SEEK_CUR) == EOF)
++                      return NULL;
++      file_header = xcursor_file_header_create(head.ntoc);
++      if (!file_header)
++              return NULL;
++      file_header->magic = head.magic;
++      file_header->header = head.header;
++      file_header->version = head.version;
++      file_header->ntoc = head.ntoc;
++      for (n = 0; n < file_header->ntoc; n++) {
++              if (!xcursor_read_uint(file, &file_header->tocs[n].type))
++                      break;
++              if (!xcursor_read_uint(file, &file_header->tocs[n].subtype))
++                      break;
++              if (!xcursor_read_uint(file, &file_header->tocs[n].position))
++                      break;
++      }
++      if (n != file_header->ntoc) {
++              xcursor_file_header_destroy(file_header);
++              return NULL;
++      }
++      return file_header;
++}
++
++static bool
++xcursor_seek_to_toc(FILE *file,
++                  struct xcursor_file_header *file_header,
++                  int toc)
++{
++      if (!file || !file_header ||
++          fseek(file, file_header->tocs[toc].position, SEEK_SET) == EOF)
++              return false;
++      return true;
++}
++
++static bool
++xcursor_file_read_chunk_header(FILE *file,
++                             struct xcursor_file_header *file_header,
++                             int toc,
++                             struct xcursor_chunk_header *chunk_header)
++{
++      if (!file || !file_header || !chunk_header)
++              return false;
++      if (!xcursor_seek_to_toc(file, file_header, toc))
++              return false;
++      if (!xcursor_read_uint(file, &chunk_header->header))
++              return false;
++      if (!xcursor_read_uint(file, &chunk_header->type))
++              return false;
++      if (!xcursor_read_uint(file, &chunk_header->subtype))
++              return false;
++      if (!xcursor_read_uint(file, &chunk_header->version))
++              return false;
++      /* sanity check */
++      if (chunk_header->type != file_header->tocs[toc].type ||
++          chunk_header->subtype != file_header->tocs[toc].subtype)
++              return false;
++      return true;
++}
++
++static uint32_t
++dist(uint32_t a, uint32_t b)
++{
++      return a > b ? a - b : b - a;
++}
++
++static uint32_t
++xcursor_file_best_size(struct xcursor_file_header *file_header,
++                     uint32_t size, int *nsizesp)
++{
++      unsigned int n;
++      int nsizes = 0;
++      uint32_t best_size = 0;
++      uint32_t this_size;
++
++      if (!file_header || !nsizesp)
++              return 0;
++
++      for (n = 0; n < file_header->ntoc; n++) {
++              if (file_header->tocs[n].type != XCURSOR_IMAGE_TYPE)
++                      continue;
++              this_size = file_header->tocs[n].subtype;
++              if (!best_size || dist(this_size, size) < dist(best_size, size)) {
++                      best_size = this_size;
++                      nsizes = 1;
++              } else if (this_size == best_size) {
++                      nsizes++;
++              }
++      }
++      *nsizesp = nsizes;
++      return best_size;
++}
++
++static int
++xcursor_find_image_toc(struct xcursor_file_header *file_header,
++                     uint32_t size, int count)
++{
++      unsigned int toc;
++      uint32_t this_size;
++
++      if (!file_header)
++              return 0;
++
++      for (toc = 0; toc < file_header->ntoc; toc++) {
++              if (file_header->tocs[toc].type != XCURSOR_IMAGE_TYPE)
++                      continue;
++              this_size = file_header->tocs[toc].subtype;
++              if (this_size != size)
++                      continue;
++              if (!count)
++                      break;
++              count--;
++      }
++      if (toc == file_header->ntoc)
++              return -1;
++      return toc;
++}
++
++static struct xcursor_image *
++xcursor_read_image(FILE *file,
++                 struct xcursor_file_header *file_header,
++                 int toc)
++{
++      struct xcursor_chunk_header chunk_header;
++      struct xcursor_image head;
++      struct xcursor_image *image;
++      int n;
++      uint32_t *p;
++
++      if (!file || !file_header)
++              return NULL;
++
++      if (!xcursor_file_read_chunk_header(file, file_header, toc, &chunk_header))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.width))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.height))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.xhot))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.yhot))
++              return NULL;
++      if (!xcursor_read_uint(file, &head.delay))
++              return NULL;
++      /* sanity check data */
++      if (head.width > XCURSOR_IMAGE_MAX_SIZE ||
++          head.height > XCURSOR_IMAGE_MAX_SIZE)
++              return NULL;
++      if (head.width == 0 || head.height == 0)
++              return NULL;
++      if (head.xhot > head.width || head.yhot > head.height)
++              return NULL;
++
++      /* Create the image and initialize it */
++      image = xcursor_image_create(head.width, head.height);
++      if (image == NULL)
++              return NULL;
++      if (chunk_header.version < image->version)
++              image->version = chunk_header.version;
++      image->size = chunk_header.subtype;
++      image->xhot = head.xhot;
++      image->yhot = head.yhot;
++      image->delay = head.delay;
++      n = image->width * image->height;
++      p = image->pixels;
++      while (n--) {
++              if (!xcursor_read_uint(file, p)) {
++                      xcursor_image_destroy(image);
++                      return NULL;
++              }
++              p++;
++      }
++      return image;
++}
++
++static struct xcursor_images *
++xcursor_xc_file_load_images(FILE *file, int size)
++{
++      struct xcursor_file_header *file_header;
++      uint32_t best_size;
++      int nsize;
++      struct xcursor_images *images;
++      int n;
++      int toc;
++
++      if (!file || size < 0)
++              return NULL;
++      file_header = xcursor_read_file_header(file);
++      if (!file_header)
++              return NULL;
++      best_size = xcursor_file_best_size(file_header, (uint32_t) size, &nsize);
++      if (!best_size) {
++              xcursor_file_header_destroy(file_header);
++              return NULL;
++      }
++      images = xcursor_images_create(nsize);
++      if (!images) {
++              xcursor_file_header_destroy(file_header);
++              return NULL;
++      }
++      for (n = 0; n < nsize; n++) {
++              toc = xcursor_find_image_toc(file_header, best_size, n);
++              if (toc < 0)
++                      break;
++              images->images[images->nimage] = xcursor_read_image(file, file_header,
++                                                                  toc);
++              if (!images->images[images->nimage])
++                      break;
++              images->nimage++;
++      }
++      xcursor_file_header_destroy(file_header);
++      if (images->nimage != nsize) {
++              xcursor_images_destroy(images);
++              images = NULL;
++      }
++      return images;
++}
++
++/*
++ * From libXcursor/src/library.c
++ */
++
++#ifndef ICONDIR
++#define ICONDIR "/usr/X11R6/lib/X11/icons"
++#endif
++
++#ifndef XCURSORPATH
++#define XCURSORPATH "~/.icons:/usr/share/icons:/usr/share/pixmaps:~/.cursors:/usr/share/cursors/xorg-x11:"ICONDIR
++#endif
++
++#define XDG_DATA_HOME_FALLBACK "~/.local/share"
++#define CURSORDIR "/icons"
++
++/** Get search path for cursor themes
++ *
++ * This function builds the list of directories to look for cursor
++ * themes in.  The format is PATH-like: directories are separated by
++ * colons.
++ *
++ * The memory block returned by this function is allocated on the heap
++ * and must be freed by the caller.
++ */
++static char *
++xcursor_library_path(void)
++{
++      const char *env_var, *suffix;
++      char *path;
++      size_t path_size;
++
++      env_var = getenv("XCURSOR_PATH");
++      if (env_var)
++              return strdup(env_var);
++
++      env_var = getenv("XDG_DATA_HOME");
++      if (!env_var || env_var[0] != '/')
++              env_var = XDG_DATA_HOME_FALLBACK;
++
++      suffix = CURSORDIR ":" XCURSORPATH;
++      path_size = strlen(env_var) + strlen(suffix) + 1;
++      path = malloc(path_size);
++      if (!path)
++              return NULL;
++      snprintf(path, path_size, "%s%s", env_var, suffix);
++      return path;
++}
++
++static char *
++xcursor_build_theme_dir(const char *dir, const char *theme)
++{
++      const char *colon;
++      const char *tcolon;
++      char *full;
++      const char *home, *homesep;
++      int dirlen;
++      int homelen;
++      int themelen;
++      size_t full_size;
++
++      if (!dir || !theme)
++              return NULL;
++
++      colon = strchr(dir, ':');
++      if (!colon)
++              colon = dir + strlen(dir);
++
++      dirlen = colon - dir;
++
++      tcolon = strchr(theme, ':');
++      if (!tcolon)
++              tcolon = theme + strlen(theme);
++
++      themelen = tcolon - theme;
++
++      home = "";
++      homelen = 0;
++      homesep = "";
++      if (*dir == '~') {
++              home = getenv("HOME");
++              if (!home)
++                      return NULL;
++              homelen = strlen(home);
++              homesep = "/";
++              dir++;
++              dirlen--;
++      }
++
++      /*
++       * add space for any needed directory separators, one per component,
++       * and one for the trailing null
++       */
++      full_size = 1 + homelen + 1 + dirlen + 1 + themelen + 1;
++      full = malloc(full_size);
++      if (!full)
++              return NULL;
++      snprintf(full, full_size, "%s%s%.*s/%.*s", home, homesep,
++               dirlen, dir, themelen, theme);
++      return full;
++}
++
++static char *
++xcursor_build_fullname(const char *dir, const char *subdir, const char *file)
++{
++      char *full;
++      size_t full_size;
++
++      if (!dir || !subdir || !file)
++              return NULL;
++
++      full_size = strlen(dir) + 1 + strlen(subdir) + 1 + strlen(file) + 1;
++      full = malloc(full_size);
++      if (!full)
++              return NULL;
++      snprintf(full, full_size, "%s/%s/%s", dir, subdir, file);
++      return full;
++}
++
++static const char *
++xcursor_next_path(const char *path)
++{
++      char *colon = strchr(path, ':');
++
++      if (!colon)
++              return NULL;
++      return colon + 1;
++}
++
++static bool
++xcursor_white(char c)
++{
++      return c == ' ' || c == '\t' || c == '\n';
++}
++
++static bool
++xcursor_sep(char c)
++{
++      return c == ';' || c == ',';
++}
++
++static char *
++xcursor_theme_inherits(const char *full)
++{
++      char *line = NULL;
++      size_t line_size = 0;
++      char *result = NULL;
++      FILE *f;
++
++      if (!full)
++              return NULL;
++
++      f = fopen(full, "r");
++      if (!f)
++              return NULL;
++
++      while (getline(&line, &line_size, f) >= 0) {
++              const char *l;
++              char *r;
++
++              if (strncmp(line, "Inherits", 8))
++                      continue;
++
++              l = line + 8;
++              while (*l == ' ')
++                      l++;
++              if (*l != '=')
++                      continue;
++              l++;
++              while (*l == ' ')
++                      l++;
++              result = malloc(strlen(l) + 1);
++              if (!result)
++                      break;
++
++              r = result;
++              while (*l) {
++                      while (xcursor_sep(*l) || xcursor_white(*l))
++                              l++;
++                      if (!*l)
++                              break;
++                      if (r != result)
++                              *r++ = ':';
++                      while (*l && !xcursor_white(*l) && !xcursor_sep(*l))
++                              *r++ = *l++;
++              }
++              *r++ = '\0';
++
++              break;
++      }
++
++      fclose(f);
++      free(line);
++
++      return result;
++}
++
++static void
++load_all_cursors_from_dir(const char *path, int size,
++                        void (*load_callback)(struct xcursor_images *, void *),
++                        void *user_data)
++{
++      FILE *f;
++      DIR *dir = opendir(path);
++      struct dirent *ent;
++      char *full;
++      struct xcursor_images *images;
++
++      if (!dir)
++              return;
++
++      for (ent = readdir(dir); ent; ent = readdir(dir)) {
++#ifdef _DIRENT_HAVE_D_TYPE
++              if (ent->d_type != DT_UNKNOWN &&
++                  ent->d_type != DT_REG &&
++                  ent->d_type != DT_LNK)
++                      continue;
++#endif
++
++              full = xcursor_build_fullname(path, "", ent->d_name);
++              if (!full)
++                      continue;
++
++              f = fopen(full, "r");
++              if (!f) {
++                      free(full);
++                      continue;
++              }
++
++              images = xcursor_xc_file_load_images(f, size);
++
++              if (images) {
++                      images->name = strdup(ent->d_name);
++                      load_callback(images, user_data);
++              }
++
++              fclose(f);
++              free(full);
++      }
++
++      closedir(dir);
++}
++
++/** Load all the cursor of a theme
++ *
++ * This function loads all the cursor images of a given theme and its
++ * inherited themes. Each cursor is loaded into an struct xcursor_images object
++ * which is passed to the caller's load callback. If a cursor appears
++ * more than once across all the inherited themes, the load callback
++ * will be called multiple times, with possibly different struct xcursor_images
++ * object which have the same name. The user is expected to destroy the
++ * struct xcursor_images objects passed to the callback with
++ * xcursor_images_destroy().
++ *
++ * \param theme The name of theme that should be loaded
++ * \param size The desired size of the cursor images
++ * \param load_callback A callback function that will be called
++ * for each cursor loaded. The first parameter is the struct xcursor_images
++ * object representing the loaded cursor and the second is a pointer
++ * to data provided by the user.
++ * \param user_data The data that should be passed to the load callback
++ */
++void
++xcursor_load_theme(const char *theme, int size,
++                 void (*load_callback)(struct xcursor_images *, void *),
++                 void *user_data)
++{
++      char *full, *dir;
++      char *inherits = NULL;
++      const char *path, *i;
++      char *xcursor_path;
++
++      if (!theme)
++              theme = "default";
++
++      xcursor_path = xcursor_library_path();
++      for (path = xcursor_path;
++           path;
++           path = xcursor_next_path(path)) {
++              dir = xcursor_build_theme_dir(path, theme);
++              if (!dir)
++                      continue;
++
++              full = xcursor_build_fullname(dir, "cursors", "");
++              load_all_cursors_from_dir(full, size, load_callback,
++                                        user_data);
++              free(full);
++
++              if (!inherits) {
++                      full = xcursor_build_fullname(dir, "", "index.theme");
++                      inherits = xcursor_theme_inherits(full);
++                      free(full);
++              }
++
++              free(dir);
++      }
++
++      for (i = inherits; i; i = xcursor_next_path(i))
++              xcursor_load_theme(i, size, load_callback, user_data);
++
++      free(inherits);
++      free(xcursor_path);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..459f8166869e420c1225006a5d7156709a7f81a0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,58 @@@
++/*
++ * Copyright © 2002 Keith Packard
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef XCURSOR_H
++#define XCURSOR_H
++
++#include <stdint.h>
++
++struct xcursor_image {
++      uint32_t version; /* version of the image data */
++      uint32_t size; /* nominal size for matching */
++      uint32_t width; /* actual width */
++      uint32_t height; /* actual height */
++      uint32_t xhot; /* hot spot x (must be inside image) */
++      uint32_t yhot; /* hot spot y (must be inside image) */
++      uint32_t delay; /* animation delay to next frame (ms) */
++      uint32_t *pixels; /* pointer to pixels */
++};
++
++/*
++ * Other data structures exposed by the library API
++ */
++struct xcursor_images {
++      int nimage; /* number of images */
++      struct xcursor_image **images; /* array of XcursorImage pointers */
++      char *name; /* name used to load images */
++};
++
++void
++xcursor_images_destroy(struct xcursor_images *images);
++
++void
++xcursor_load_theme(const char *theme, int size,
++                 void (*load_callback)(struct xcursor_images *, void *),
++                 void *user_data);
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d68d6fce7035af61ff79ff44383f54405202db88
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++doxygen_sqlite3.db
++html/
++wayland.doxygen
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f2c35075e73839a46df7f58ff6edda5fd0bf0651
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,36 @@@
++digraph arch_wayland {
++    edge[
++        fontname="DejaVu Sans",
++        dir="both",
++        arrowtail="dot",
++        arrowsize=.5,
++        fontname="DejaVu Sans",
++        fontsize="18",
++    ]
++
++    node[
++        color=none,
++        margin=0,
++        fontname="DejaVu Sans",
++        fontsize="18",
++   ]
++
++    c1 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>Wayland Client</TD></TR></TABLE>>, URL="#c1"]
++    c2 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>Wayland Client</TD></TR></TABLE>>, URL="#c2"]
++
++    comp [tooltip="Wayland Compositor", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>Wayland<BR/>Compositor<BR/><BR/></TD></TR></TABLE>>, URL="#comp"]
++
++    impl [tooltip="KMS evdev Kernel", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>KMS</TD><TD>evdev</TD></TR><TR><TD COLSPAN="2">Kernel</TD></TR></TABLE>>, URL="#impl"]
++
++    c1 -> comp [taillabel="③", labeldistance=2.5, URL="#step_3"];
++    c2 -> comp;
++
++    comp -> c1 [label="②", URL="#step_2"];
++    comp -> c2;
++
++    comp -> impl [xlabel = "④", URL="#step_4"];
++    comp -> impl [style = invis, label="    "];
++    impl -> comp [xlabel = "①", URL="#step_1"];
++
++    c1 -> c2 [style=invis];
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b223d1dcad44ff3578d09e8fd548dbda32e265d7
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,53 @@@
++digraph arch_x {
++    edge[
++        fontname="DejaVu Sans",
++        dir="both",
++        arrowtail="dot",
++        arrowsize=.5,
++        fontname="DejaVu Sans",
++        fontsize="18",
++    ]
++
++    node[
++        shape="none",
++        color=none,
++        margin=0,
++        fontname="DejaVu Sans",
++        fontsize="18",
++    ]
++
++    {
++        rank=same;
++        c1 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c1"]
++        c3 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c3"]
++    }
++    c2 [label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>X Client</TD></TR></TABLE>>, URL="#c2"]
++
++    {
++        rank=same;
++        xserver [tooltip="X Server", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>X Server<BR/><BR/></TD></TR></TABLE>>, URL="#xserver"]
++        comp [tooltip="Compositor", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD><BR/>Compositor<BR/><BR/></TD></TR></TABLE>>, URL="#comp"]
++    }
++
++    impl [tooltip="KMS evdev Kernel", label=<<TABLE STYLE="rounded" BGCOLOR="#ffbc00"><TR><TD>KMS</TD><TD>evdev</TD></TR><TR><TD COLSPAN="2">Kernel</TD></TR></TABLE>>, URL="#impl"]
++
++    c1 -> xserver [taillabel="③", labeldistance=2, URL="#step_3"];
++    c2 -> xserver;
++    c3 -> xserver;
++
++    xserver -> c1 [taillabel="②", labeldistance=2, URL="#step_2"];
++    xserver -> c2;
++    xserver -> c3;
++
++    xserver -> impl [taillabel="⑥", labeldistance=1.75, URL="#step_6"];
++    xserver -> impl [style=invis, label="    "];
++    impl -> xserver [taillabel="①", labeldistance=1.75, URL="#step_1"];
++
++    xserver -> comp [style=invis];
++    xserver -> comp [taillabel="④", labeldistance=1.75, labelangle=-45, URL="#step_4"];
++    comp -> xserver [taillabel="⑤", URL="#step_5"];
++    comp -> xserver [style=invis]
++
++    c1 -> c2 [style=invis];
++    c3 -> c2 [style=invis];
++ }
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1bb07e571f123c720317799a53dd9f9a770b7353
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,105 @@@
++#!/usr/bin/env python3
++
++import argparse
++import datetime
++import errno
++import os
++import subprocess
++import sys
++
++# Custom configuration for each documentation format
++doxygen_templates = {
++    'xml': [
++        'GENERATE_XML=YES\n',
++        'XML_OUTPUT={format}/{section}\n',
++        'INPUT= {files}\n',
++    ],
++    'html': [
++        'GENERATE_HTML=YES\n',
++        'HTML_OUTPUT={format}/{section}\n',
++        'PROJECT_NAME=\"Wayland {section} API\"\n',
++        'INPUT= {files}\n',
++    ],
++    'man': [
++        'GENERATE_MAN=YES\n',
++        'MAN_OUTPUT={format}\n',
++        'MAN_SUBDIR=.\n',
++        'JAVADOC_AUTOBRIEF=NO\n',
++        'INPUT= {files}\n',
++    ],
++}
++
++def load_doxygen_file(doxyfile):
++    with open(doxyfile, 'r') as f:
++        res = f.readlines()
++    return res
++
++def get_template(outformat):
++    for (k,v) in doxygen_templates.items():
++        if outformat.startswith(k):
++            return v
++
++def gen_doxygen_file(data, outformat, section, files):
++    for l in get_template(outformat):
++        data.append(l.format(format=outformat, section=section, files=' '.join(files)))
++    return data
++
++parser = argparse.ArgumentParser(description='Generate docs with Doxygen')
++parser.add_argument('doxygen_file',
++                    help='The doxygen file to use')
++parser.add_argument('files',
++                    help='The list of files to parse',
++                    metavar='FILES',
++                    nargs='+')
++parser.add_argument('--builddir',
++                    help='The build directory',
++                    metavar='DIR',
++                    default='.')
++parser.add_argument('--section',
++                    help='The section to build',
++                    metavar='NAME',
++                    default='Client')
++parser.add_argument('--output-format',
++                    help='The output format: xml, html, man',
++                    metavar='FORMAT',
++                    default='xml')
++parser.add_argument('--stamp',
++                    help='Stamp file to output',
++                    metavar='STAMP_FILE',
++                    nargs='?',
++                    type=argparse.FileType('w'))
++
++args = parser.parse_args()
++
++# Merge the doxyfile with our custom templates
++conf = load_doxygen_file(args.doxygen_file)
++conf = gen_doxygen_file(conf, args.output_format, args.section, args.files)
++
++# Doxygen is not clever enough to create the directories it
++# needs beforehand
++try:
++    os.makedirs(os.path.join(args.builddir, args.output_format))
++except OSError as e:
++    if e.errno != errno.EEXIST:
++        raise e
++
++# Run Doxygen with the generated doxyfile
++cmd = subprocess.Popen(['doxygen', '-'], stdin=subprocess.PIPE)
++cmd.stdin.write(''.join(conf).encode('utf-8'))
++cmd.stdin.close()
++if cmd.wait() != 0:
++    sys.exit(1)
++
++# This is a bit of a hack; Doxygen will generate way more files than we
++# want to install, but there's no way to know how many at configuration
++# time. Since we want to install only the wl_* man pages anyway, we can
++# delete the other files and let Meson install the whole man3 subdirectory
++if args.output_format.startswith('man'):
++    manpath = os.path.join(args.builddir, args.output_format)
++    for filename in os.listdir(manpath):
++        full_path = os.path.join(manpath, filename)
++        if not filename.startswith('wl_'):
++            os.remove(full_path)
++
++if args.stamp:
++   args.stamp.write(str(datetime.datetime.now()))
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..352f69beae5001833383eda0d1deea7df838c84c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,23 @@@
++/**
++ * @mainpage
++ * Wayland protocol API documentation.
++ *
++ * This documentation is available for the Server- and the Client-side APIs.
++ *
++ * - <a href="../Server/index.html">Server-side API</a>
++ * - <a href="../Client/index.html">Client-side API</a>
++ * - <a href="../Cursor/index.html">Cursor helper library API</a>
++ *
++ * Further documentation about the architecture and principles of Wayland is
++ * available in the
++ * <a href="https://wayland.freedesktop.org/docs/html">Wayland Book</a>
++ *
++ * @section ifaces Interfaces
++ * For the list of available interfaces, please see the
++ * <a href="modules.html">modules</a> list.
++ *
++ * @section protocols Protocols
++ * For the list of protocols, please see the
++ * <a href="pages.html">Related Pages</a>.
++ *
++ */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..611262064a46e28662f39e59d3bde90aa683b090
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,117 @@@
++# Here be dragons
++
++dot_gv = {
++      'wayland-architecture': files('dot/wayland-architecture.gv'),
++      'x-architecture': files('dot/x-architecture.gv'),
++}
++
++# This is a workaround for Meson's custom_target() directive, which
++# currently does not support outputs pointing to a sub-directory
++# XXX: try turning these into maps, so they can be indexed with picture name
++dot_png = []
++dot_map = []
++
++doxygen_conf = configuration_data()
++doxygen_conf.set('VERSION', meson.project_version())
++doxygen_conf.set('top_builddir', meson.project_build_root())
++wayland_doxygen = configure_file(
++      input: 'wayland.doxygen.in',
++      output: 'wayland.doxygen',
++      configuration: doxygen_conf,
++)
++
++shared_files = files([
++      '../../src/wayland-util.h',
++])
++
++client_files = files([
++      '../../src/wayland-client.c',
++      '../../src/wayland-client.h',
++      '../../src/wayland-client-core.h',
++])
++
++server_files = files([
++      '../../src/event-loop.c',
++      '../../src/wayland-server.c',
++      '../../src/wayland-server.h',
++      '../../src/wayland-server-core.h',
++      '../../src/wayland-shm.c',
++])
++
++cursor_files = files([
++      '../../cursor/wayland-cursor.c',
++      '../../cursor/wayland-cursor.h',
++])
++
++extra_client_files = [
++      'mainpage.dox',
++      wayland_client_protocol_h,
++]
++
++extra_server_files = [
++      'mainpage.dox',
++      wayland_server_protocol_h,
++]
++
++extra_cursor_files = [
++      'mainpage.dox',
++]
++
++gen_doxygen = find_program('gen-doxygen.py')
++
++subdir('xml')
++
++formats = {
++      'html': {
++              'Client': shared_files + client_files + extra_client_files,
++              'Server': shared_files + server_files + extra_server_files,
++              'Cursor': shared_files + cursor_files + extra_cursor_files,
++      },
++}
++
++foreach f_name, sections: formats
++      foreach s_name, s_files: sections
++              t_name = '@0@-@1@-doc'.format(f_name, s_name)
++
++              # We do not really need an output file, but Meson
++              # will complain if one is not set, so we use a
++              # dummy 'stamp' file
++              stamp = join_paths(meson.current_build_dir(), '@0@.stamp'.format(t_name))
++              custom_target(
++                      t_name,
++                      command: [
++                              gen_doxygen,
++                              # XXX pass doxygen path as argument
++                              '--builddir=@OUTDIR@',
++                              '--section=@0@'.format(s_name),
++                              '--output-format=@0@'.format(f_name),
++                              '--stamp=@0@'.format(stamp),
++                              wayland_doxygen,
++                              '@INPUT@',
++                      ],
++                      input: s_files,
++                      output: '@0@.stamp'.format(t_name),
++                      depends: [dot_png, dot_map],
++                      build_by_default: true,
++              )
++      endforeach
++endforeach
++
++man_files = shared_files + server_files + client_files + cursor_files
++stamp = join_paths(meson.current_build_dir(), 'man3.stamp')
++custom_target(
++      'man-pages-3',
++      command: [
++              gen_doxygen,
++              '--builddir=@OUTDIR@',
++              '--output-format=man3',
++              '--stamp=@0@'.format(stamp),
++              wayland_doxygen,
++              '@INPUT@',
++      ],
++      input: man_files,
++      output: 'man3',
++      build_by_default: true,
++      install: true,
++      install_dir: join_paths(get_option('prefix'), get_option('mandir')),
++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..60c5fbbb8e8a2003e553cf5157c0b73d0e990248
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,23 @@@
++# Wayland-specific overrides
++PROJECT_NAME           = "Wayland"
++PROJECT_NUMBER         = @VERSION@
++OUTPUT_DIRECTORY       = @top_builddir@/doc/doxygen
++JAVADOC_AUTOBRIEF      = YES
++TAB_SIZE               = 8
++QUIET                  = YES
++HTML_TIMESTAMP         = YES
++GENERATE_LATEX         = NO
++MAN_LINKS              = NO
++PREDEFINED             = WL_EXPORT=              \
++                         WL_PRINTF(x,y)=
++MACRO_EXPANSION        = YES
++EXPAND_ONLY_PREDEF     = YES
++DOT_MULTI_TARGETS      = YES
++ALIASES                += comment{1}="/* \1 *<!-- -->/"
++OPTIMIZE_OUTPUT_FOR_C  = YES
++EXTRACT_ALL            = YES
++EXTRACT_STATIC         = YES
++# These must be set in the Makefile
++GENERATE_HTML          = NO
++GENERATE_XML           = NO
++GENERATE_MAN           = NO
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..849c30da68192b27239755084e56852b6c0e1f29
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++tgt = custom_target(
++      'xml-Client-doc',
++      command: [
++              gen_doxygen,
++              # XXX pass doxygen path as argument
++              '--builddir=@OUTDIR@',
++              '--section=Client',
++              '--output-format=xml',
++              wayland_doxygen,
++              '@INPUT@',
++      ],
++      input: [ shared_files, client_files ],
++      output: [ 'combine.xslt', 'index.xml' ],
++      depends: [dot_png, dot_map]
++)
++
++doxygen_Client_combine_xslt = tgt[0]
++doxygen_Client_index_xml = tgt[1]
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4792c1bcdfc42151ff2e0d516ec64e7bf039ea87
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++tgt = custom_target(
++      'xml-Server-doc',
++      command: [
++              gen_doxygen,
++              # XXX pass doxygen path as argument
++              '--builddir=@OUTDIR@',
++              '--section=Server',
++              '--output-format=xml',
++              wayland_doxygen,
++              '@INPUT@',
++      ],
++      input: [ shared_files, server_files ],
++      output: [ 'combine.xslt', 'index.xml' ],
++      depends: [dot_png, dot_map]
++)
++
++doxygen_Server_combine_xslt = tgt[0]
++doxygen_Server_index_xml = tgt[1]
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6d55c53afef2819be5097887e9c8e426e242afe0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,22 @@@
++# dot_png: list of PNG targets
++# dot_map: list of MAP targets
++foreach name, infile: dot_gv
++      dot_png += custom_target(
++              name + '.png',
++              command: [ dot, '-Tpng', '-o@OUTPUT@', '@INPUT@' ],
++              input: infile,
++              output: name + '.png',
++              install: true,
++              install_dir: join_paths(publican_install_prefix, publican_html_dir, 'images')
++      )
++
++      dot_map += custom_target(
++              name + '.map',
++              command: [ dot, '-Tcmapx_np', '-o@OUTPUT@', '@INPUT@' ],
++              input: infile,
++              output: name + '.map',
++      )
++endforeach
++
++subdir('Client')
++subdir('Server')
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..44fda2abf868235faa8fe67150e474f063710598
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,41 @@@
++if not get_option('libraries')
++      error('-Ddocumentation=true requires -Dlibraries=true')
++endif
++
++dot = find_program('dot')
++doxygen = find_program('doxygen')
++xsltproc = find_program('xsltproc')
++xmlto = find_program('xmlto')
++
++cmd = run_command(doxygen, '--version', check: true)
++message('doxygen: ' + cmd.stdout().strip())
++vers = cmd.stdout().strip()
++if vers.version_compare('< 1.6.0')
++      error('Doxygen 1.6 or later is required for building documentation, found @0@.'.format(vers))
++endif
++
++cmd = run_command(dot, '-V', check: true)
++message('dot: ' + cmd.stderr().strip())
++vers = cmd.stderr().split('version')[1].strip().split(' ')[0]
++if vers.version_compare('< 2.26.0')
++      error('Dot (Graphviz) 2.26 or later is required for building documentation, found @0@.'.format(vers))
++endif
++
++manpage_xsl = 'http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl'
++cmd = run_command(xsltproc, '--nonet', manpage_xsl, check: false)
++if cmd.returncode() != 0
++      error('The style sheet for man pages providing "@0@" was not found.'.format(manpage_xsl))
++endif
++
++publican_install_prefix = join_paths(
++      get_option('prefix'),
++      get_option('datadir'),
++      'doc',
++      meson.project_name(),
++      'Wayland', 'en-US'
++)
++
++publican_html_dir = 'html'
++
++subdir('doxygen')
++subdir('publican')
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c1656e70da7a8cf6b48cac76a29ef92276dfa91f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++Wayland
++en-US/
++publican-copy.cfg
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e13dcd7684fe3a0352745c54355befda0d48f942
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,147 @@@
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++<xsl:param name="which" />
++
++<xsl:template match="/">
++  <xsl:apply-templates select="/doxygen/compounddef[@kind!='file' and @kind!='dir']" />
++
++  <section id="{$which}-Functions">
++    <title>Functions</title>
++    <para />
++    <variablelist>
++      <xsl:apply-templates select="/doxygen/compounddef[@kind='file']/sectiondef/memberdef" />
++    </variablelist>
++  </section>
++
++</xsl:template>
++
++<xsl:template match="parameteritem">
++    <varlistentry>
++        <term>
++          <xsl:apply-templates select="parameternamelist/parametername"/>
++        </term>
++      <listitem>
++        <simpara><xsl:apply-templates select="parameterdescription"/></simpara>
++      </listitem>
++    </varlistentry>
++</xsl:template>
++
++<xsl:template match="parameterlist">
++  <xsl:if test="parameteritem">
++      <variablelist>
++        <xsl:apply-templates select="parameteritem" />
++      </variablelist>
++  </xsl:if>
++</xsl:template>
++
++<xsl:template match="ref">
++  <link linkend="{$which}-{@refid}"><xsl:value-of select="." /></link>
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='return']">
++  <variablelist>
++    <varlistentry>
++      <term>Returns:</term>
++      <listitem>
++        <simpara><xsl:apply-templates /></simpara>
++      </listitem>
++    </varlistentry>
++  </variablelist>
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='see']">
++  See also: <xsl:apply-templates />
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='since']">
++  Since: <xsl:apply-templates />
++</xsl:template>
++
++<xsl:template match="simplesect[@kind='note']">
++  <emphasis>Note: <xsl:apply-templates /></emphasis>
++</xsl:template>
++
++<xsl:template match="sp">
++  <xsl:text> </xsl:text>
++</xsl:template>
++
++<xsl:template match="programlisting">
++  <programlisting><xsl:apply-templates /></programlisting>
++</xsl:template>
++
++<xsl:template match="itemizedlist">
++  <itemizedlist><xsl:apply-templates select="listitem" /></itemizedlist>
++</xsl:template>
++
++<xsl:template match="listitem">
++  <listitem><simpara><xsl:apply-templates /></simpara></listitem>
++</xsl:template>
++
++<!-- stops cross-references in the section titles -->
++<xsl:template match="briefdescription">
++  <xsl:value-of select="." />
++</xsl:template>
++
++<!-- this opens a para for each detaileddescription/para. I could not find a
++     way to extract the right text for the description from the
++     source otherwise. Downside: we can't use para for return value, "see
++     also", etc.  because they're already inside a para. So they're lists.
++
++     It also means we don't control the order of when something is added to
++     the output, it matches the input file
++     -->
++<xsl:template match="detaileddescription/para">
++  <para><xsl:apply-templates /></para>
++</xsl:template>
++
++<xsl:template match="detaileddescription">
++  <xsl:apply-templates select="para" />
++</xsl:template>
++
++<!-- methods -->
++<xsl:template match="memberdef" >
++  <xsl:if test="@kind = 'function' and @static = 'no' and @prot = 'public' or
++                @kind !='function' and normalize-space(briefdescription) != ''">
++    <varlistentry id="{$which}-{@id}">
++        <term>
++          <xsl:value-of select="name"/>
++          <xsl:if test="normalize-space(briefdescription) != ''">
++            - <xsl:apply-templates select="briefdescription" />
++          </xsl:if>
++        </term>
++        <listitem>
++          <synopsis>
++            <xsl:apply-templates select="definition"/><xsl:apply-templates select="argsstring"/>
++          </synopsis>
++          <xsl:apply-templates select="detaileddescription" />
++        </listitem>
++    </varlistentry>
++  </xsl:if>
++</xsl:template>
++
++<!-- classes -->
++<xsl:template match="compounddef" >
++    <section id="{$which}-{@id}">
++        <title>
++            <xsl:value-of select="compoundname" />
++            <xsl:if test="normalize-space(briefdescription) != ''">
++                - <xsl:apply-templates select="briefdescription" />
++            </xsl:if>
++        </title>
++        <xsl:choose>
++          <xsl:when test="normalize-space(detaileddescription) != ''">
++            <xsl:apply-templates select="detaileddescription" />
++          </xsl:when>
++          <xsl:otherwise>
++            <para />
++          </xsl:otherwise>
++        </xsl:choose>
++        <xsl:if test="sectiondef/memberdef[@kind='function' and @static='no']">
++          <variablelist>
++            <xsl:apply-templates select="sectiondef/memberdef" />
++          </variablelist>
++        </xsl:if>
++    </section>
++</xsl:template>
++</xsl:stylesheet>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7adaca3665bbf93f0c8d6616ce734abebf48b68f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,64 @@@
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++  <xsl:param name="basedir"/>
++  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
++  <!-- -->
++  <!-- Template for the root so we can add a DOCTYPE -->
++  <xsl:template match="/">
++    <xsl:text disable-output-escaping="yes"><![CDATA[<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++    <xsl:apply-templates select="@*|node()"/>
++  </xsl:template>
++  <!-- -->
++  <xsl:template match="@*|node()">
++    <xsl:copy>
++      <xsl:apply-templates select="@*|node()"/>
++    </xsl:copy>
++  </xsl:template>
++  <!-- -->
++  <!-- suppress existing image map areas -->
++  <xsl:template match="area"/>
++  <!-- -->
++  <xsl:template match="areaspec[area][name(..)='imageobjectco']">
++    <xsl:element name="areaspec">
++      <xsl:apply-templates select="@*"/>
++      <xsl:text>&#xa;</xsl:text>
++      <xsl:variable name="pngfile" select="../imageobject/imagedata/@fileref"/>
++      <xsl:variable name="mapfile" select="concat(substring($pngfile, 1, string-length($pngfile)-3), 'map')"/>
++      <xsl:variable name="maproot" select="document(concat($basedir, '/', $mapfile))"/>
++      <!-- -->
++      <!-- now emit the needed areas -->
++      <xsl:for-each select="area">
++      <xsl:variable name="anchor" select="."/>
++      <xsl:variable name="other" select="($maproot)//area[@href=($anchor)/@x_steal]"/>
++      <xsl:choose>
++        <xsl:when test="$other">
++          <xsl:text>&#x9;    </xsl:text>
++          <xsl:element name="area">
++            <xsl:attribute name="id">
++              <xsl:value-of select="@id"/>
++            </xsl:attribute>
++            <xsl:attribute name="linkends">
++              <xsl:value-of select="@linkends"/>
++            </xsl:attribute>
++            <xsl:attribute name="coords">
++              <xsl:value-of select="($other)/@coords"/>
++            </xsl:attribute>
++          </xsl:element>
++        </xsl:when>
++        <xsl:otherwise>
++          <xsl:text>&#x9;    </xsl:text>
++          <xsl:comment>
++            <xsl:value-of select="concat('Warning: unable to locate area tagged ', ($anchor)/@x_steal)"/>
++          </xsl:comment>
++        </xsl:otherwise>
++      </xsl:choose>
++      <xsl:text>&#xa;</xsl:text>
++      </xsl:for-each>
++      <!-- -->
++      <xsl:text>&#x9;  </xsl:text>
++    </xsl:element>
++  </xsl:template>
++</xsl:stylesheet>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..eac3e9b2931df50401d0e33fd02dbf953b279034
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,32 @@@
++merge_mapcoords_xsl = files('merge-mapcoords.xsl')
++
++subdir('sources')
++
++custom_target(
++      'Wayland-docbook-html',
++      command: [
++              xmlto,
++              '--skip-validation',
++              '--stringparam', 'chunker.output.encoding=UTF-8',
++              '--stringparam', 'chunk.section.depth=0',
++              '--stringparam', 'toc.section.depth=1',
++              '--stringparam', 'generate.consistent.ids=1',
++              '--stringparam', 'html.stylesheet=css/default.css',
++              '-o', '@OUTPUT@',
++              'html',
++              '@INPUT@'
++      ],
++      input: publican_processed_main,
++      output: publican_html_dir,
++      depend_files: publican_copied_sources,
++      depends: [
++              publican_processed_targets,
++              ClientAPI_xml,
++              ServerAPI_xml,
++              ProtocolSpec_xml,
++              ProtocolInterfaces_xml
++      ],
++      build_by_default: true,
++      install: true,
++      install_dir: publican_install_prefix
++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f68216d57e2d86dcde15fe5f9156294625e1bb3e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++
++<xsl:template match="/">
++  <!-- insert docbook's DOCTYPE blurb -->
++    <xsl:text disable-output-escaping = "yes"><![CDATA[
++<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++  <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++
++  <section id="sect-Protocol-Interfaces">
++    <title>Interfaces</title>
++    <para>
++      The protocol includes several interfaces which are used for
++      interacting with the server.  Each interface provides requests,
++      events, and errors (which are really just special events) as described
++      above.  Specific compositor implementations may have their own
++      interfaces provided as extensions, but there are several which are
++      always expected to be present.
++    </para>
++
++    <para>
++      Core interfaces:
++      <variablelist>
++        <xsl:apply-templates select="protocol/interface" />
++      </variablelist>
++    </para>
++  </section>
++</xsl:template>
++
++<!-- Interfaces summary -->
++<xsl:template match="interface" >
++<varlistentry>
++  <term>
++    <link linkend="protocol-spec-{@name}">
++      <xsl:value-of select="@name" />
++    </link>
++  </term>
++  <listitem>
++    <simpara>
++      <xsl:value-of select="description/@summary" />
++    </simpara>
++  </listitem>
++</varlistentry>
++</xsl:template>
++
++</xsl:stylesheet>
++<!-- vim: set expandtab shiftwidth=2: -->
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..79c938bb3a1c6c184feca68654b9da5f8446526a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,223 @@@
++<?xml version="1.0" ?>
++<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
++<xsl:output method="xml" encoding="UTF-8" indent="yes" />
++
++<xsl:template match="/">
++  <!-- insert docbook's DOCTYPE blurb -->
++    <xsl:text disable-output-escaping = "yes"><![CDATA[
++<!DOCTYPE appendix PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++  <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++]]></xsl:text>
++
++  <appendix id="appe-Wayland-Protocol">
++    <title>Wayland Protocol Specification</title>
++    <xsl:apply-templates select="protocol/copyright" />
++
++    <xsl:apply-templates select="protocol/interface" />
++  </appendix>
++</xsl:template>
++
++<!-- Break text blocks separated by two new lines into paragraphs -->
++<xsl:template name="break">
++     <xsl:param name="text" />
++     <xsl:param name="linebreak" select="'&#10;&#10;'" />
++     <xsl:choose>
++       <xsl:when test="contains($text,$linebreak)">
++         <para>
++           <xsl:value-of select="substring-before($text,$linebreak)" />
++         </para>
++         <xsl:call-template name="break">
++           <xsl:with-param name="text" select="substring-after($text,$linebreak)" />
++         </xsl:call-template>
++       </xsl:when>
++       <xsl:otherwise>
++         <para><xsl:value-of select="$text" /></para>
++       </xsl:otherwise>
++     </xsl:choose>
++</xsl:template>
++
++<!-- Copyright blurb -->
++<xsl:template match="copyright">
++  <para>
++    <literallayout>
++      <xsl:value-of select="." disable-output-escaping="yes"/>
++    </literallayout>
++  </para>
++</xsl:template>
++
++<!-- Interface descriptions -->
++<xsl:template match="interface" >
++  <section id="protocol-spec-{@name}">
++    <title>
++      <xsl:value-of select="@name" />
++      <!-- only show summary if it exists -->
++      <xsl:if test="description/@summary">
++      - <xsl:value-of select="description/@summary" />
++      </xsl:if>
++    </title>
++    <xsl:call-template name="break">
++      <xsl:with-param name="text" select="description" />
++    </xsl:call-template>
++    <xsl:if test="request">
++      <section>
++        <title>Requests provided by <xsl:value-of select="@name" /></title>
++        <xsl:apply-templates select="request" />
++      </section>
++    </xsl:if>
++    <xsl:if test="event">
++      <section>
++        <title>Events provided by <xsl:value-of select="@name" /></title>
++        <xsl:apply-templates select="event" />
++      </section>
++    </xsl:if>
++    <xsl:if test="enum">
++      <section>
++        <title>Enums provided by <xsl:value-of select="@name" /></title>
++      <xsl:apply-templates select="enum" />
++      </section>
++    </xsl:if>
++  </section>
++</xsl:template>
++
++<!-- table contents for enum values -->
++<xsl:template match="entry">
++  <varlistentry>
++    <term><xsl:value-of select="@name"/></term>
++    <listitem>
++      <simpara>
++        <xsl:value-of select="@value"/>
++        <xsl:if test="@summary" >
++          - <xsl:value-of select="@summary"/>
++        </xsl:if>
++      </simpara>
++    </listitem>
++  </varlistentry>
++</xsl:template>
++
++<!-- table contents for request/event arguments -->
++<xsl:template match="arg">
++  <varlistentry>
++    <term><xsl:value-of select="@name"/></term>
++    <listitem>
++        <simpara>
++          <xsl:value-of select="@type"/>
++          <xsl:if test="@summary" >
++            - <xsl:value-of select="@summary"/>
++          </xsl:if>
++        </simpara>
++    </listitem>
++  </varlistentry>
++</xsl:template>
++
++<!-- id arguments -->
++<xsl:template match="arg[@type='object' and @interface]">
++  <varlistentry>
++    <term><xsl:value-of select="@name"/></term>
++    <listitem>
++        <simpara>
++          <link linkend="protocol-spec-{@interface}">
++            <xsl:value-of select="@interface"/>
++          </link>
++          <xsl:if test="@summary" >
++            - <xsl:value-of select="@summary"/>
++          </xsl:if>
++        </simpara>
++    </listitem>
++  </varlistentry>
++</xsl:template>
++
++<!-- new_id arguments -->
++<xsl:template match="arg[@type='new_id' and @interface]">
++  <varlistentry>
++    <term><xsl:value-of select="@name"/></term>
++    <listitem>
++        <simpara>
++          id for the new
++          <link linkend="protocol-spec-{@interface}">
++            <xsl:value-of select="@interface"/>
++          </link>
++          <xsl:if test="@summary" >
++            - <xsl:value-of select="@summary"/>
++          </xsl:if>
++        </simpara>
++    </listitem>
++  </varlistentry>
++</xsl:template>
++
++<!-- enum and bitfield arguments -->
++<xsl:template match="arg[@enum]">
++  <varlistentry>
++    <term><xsl:value-of select="@name"/></term>
++    <listitem>
++        <simpara>
++          <xsl:choose>
++            <xsl:when test="contains(@enum, '.')">
++              <link linkend="protocol-spec-{substring-before(@enum, '.')}-enum-{substring-after(@enum, '.')}">
++                <xsl:value-of select="substring-before(@enum, '.')"/>
++                <xsl:text>::</xsl:text>
++                <xsl:value-of select="substring-after(@enum, '.')"/>
++              </link>
++            </xsl:when>
++            <xsl:otherwise>
++              <link linkend="protocol-spec-{../../@name}-enum-{@enum}">
++                <xsl:value-of select="../../@name"/>
++                <xsl:text>::</xsl:text>
++                <xsl:value-of select="@enum"/>
++              </link>
++            </xsl:otherwise>
++          </xsl:choose>
++          (<xsl:value-of select="@type"/>)
++          <xsl:if test="@summary" >
++            - <xsl:value-of select="@summary"/>
++          </xsl:if>
++        </simpara>
++    </listitem>
++  </varlistentry>
++</xsl:template>
++
++<!-- Request/event list -->
++<xsl:template match="request|event">
++  <section id="protocol-spec-{../@name}-{name()}-{@name}">
++    <title>
++      <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
++      <xsl:if test="description/@summary">
++        - <xsl:value-of select="description/@summary" />
++      </xsl:if>
++    </title>
++    <para>
++      <variablelist>
++        <xsl:apply-templates select="arg"/>
++      </variablelist>
++    </para>
++    <xsl:call-template name="break">
++      <xsl:with-param name="text" select="description" />
++    </xsl:call-template>
++  </section>
++</xsl:template>
++
++<!-- Enumeration -->
++<xsl:template match="enum">
++  <section id="protocol-spec-{../@name}-enum-{@name}">
++    <title>
++      <xsl:value-of select="../@name"/>::<xsl:value-of select="@name" />
++      <xsl:if test="@bitfield">
++        - bitfield
++      </xsl:if>
++      <xsl:if test="description/@summary">
++        - <xsl:value-of select="description/@summary" />
++      </xsl:if>
++    </title>
++    <xsl:call-template name="break">
++      <xsl:with-param name="text" select="description" />
++    </xsl:call-template>
++    <variablelist>
++      <xsl:apply-templates select="entry"/>
++    </variablelist>
++  </section>
++</xsl:template>
++
++</xsl:stylesheet>
++
++<!-- vim: set expandtab shiftwidth=2: -->
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b8a104cfb4c0a2d589157c162e45c7f098118cf0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,344 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Wayland-Architecture">
++  <title>Wayland Architecture</title>
++  <section id="sect-Wayland-Architecture-wayland_architecture">
++    <title>X vs. Wayland Architecture</title>
++    <para>
++      A good way to understand the Wayland architecture
++      and how it is different from X is to follow an event
++      from the input device to the point where the change
++      it affects appears on screen.
++    </para>
++    <para>
++      This is where we are now with X:
++    </para>
++    <figure>
++      <title>X architecture diagram</title>
++      <mediaobjectco>
++      <imageobjectco>
++        <areaspec id="map1" units="other" otherunits="imagemap">
++          <area id="area1_1" linkends="x_flow_1" x_steal="#step_1"/>
++          <area id="area1_2" linkends="x_flow_2" x_steal="#step_2"/>
++          <area id="area1_3" linkends="x_flow_3" x_steal="#step_3"/>
++          <area id="area1_4" linkends="x_flow_4" x_steal="#step_4"/>
++          <area id="area1_5" linkends="x_flow_5" x_steal="#step_5"/>
++          <area id="area1_6" linkends="x_flow_6" x_steal="#step_6"/>
++        </areaspec>
++        <imageobject>
++          <imagedata fileref="images/x-architecture.png" format="PNG" />
++        </imageobject>
++      </imageobjectco>
++      </mediaobjectco>
++    </figure>
++    <para>
++      <orderedlist>
++      <listitem id="x_flow_1">
++        <para>
++          The kernel gets an event from an input
++          device and sends it to X through the evdev
++          input driver. The kernel does all the hard
++          work here by driving the device and
++          translating the different device specific
++          event protocols to the linux evdev input
++          event standard.
++        </para>
++      </listitem>
++      <listitem id="x_flow_2">
++        <para>
++          The X server determines which window the
++          event affects and sends it to the clients
++          that have selected for the event in question
++          on that window. The X server doesn't
++          actually know how to do this right, since
++          the window location on screen is controlled
++          by the compositor and may be transformed in
++          a number of ways that the X server doesn't
++          understand (scaled down, rotated, wobbling,
++          etc).
++        </para>
++      </listitem>
++      <listitem id="x_flow_3">
++        <para>
++          The client looks at the event and decides
++          what to do. Often the UI will have to change
++          in response to the event - perhaps a check
++          box was clicked or the pointer entered a
++          button that must be highlighted. Thus the
++          client sends a rendering request back to the
++          X server.
++        </para>
++      </listitem>
++      <listitem id="x_flow_4">
++        <para>
++          When the X server receives the rendering
++          request, it sends it to the driver to let it
++          program the hardware to do the rendering.
++          The X server also calculates the bounding
++          region of the rendering, and sends that to
++          the compositor as a damage event.
++        </para>
++      </listitem>
++      <listitem id="x_flow_5">
++        <para>
++          The damage event tells the compositor that
++          something changed in the window and that it
++          has to recomposite the part of the screen
++          where that window is visible. The compositor
++          is responsible for rendering the entire
++          screen contents based on its scenegraph and
++          the contents of the X windows. Yet, it has
++          to go through the X server to render this.
++        </para>
++      </listitem>
++      <listitem id="x_flow_6">
++        <para>
++          The X server receives the rendering requests
++          from the compositor and either copies the
++          compositor back buffer to the front buffer
++          or does a pageflip. In the general case, the
++          X server has to do this step so it can
++          account for overlapping windows, which may
++          require clipping and determine whether or
++          not it can page flip. However, for a
++          compositor, which is always fullscreen, this
++          is another unnecessary context switch.
++        </para>
++      </listitem>
++      </orderedlist>
++    </para>
++    <para>
++      As suggested above, there are a few problems with this
++      approach. The X server doesn't have the information to
++      decide which window should receive the event, nor can it
++      transform the screen coordinates to window-local
++      coordinates. And even though X has handed responsibility for
++      the final painting of the screen to the compositing manager,
++      X still controls the front buffer and modesetting. Most of
++      the complexity that the X server used to handle is now
++      available in the kernel or self contained libraries (KMS,
++      evdev, mesa, fontconfig, freetype, cairo, Qt etc). In
++      general, the X server is now just a middle man that
++      introduces an extra step between applications and the
++      compositor and an extra step between the compositor and the
++      hardware.
++    </para>
++    <para>
++      In Wayland the compositor is the display server. We transfer
++      the control of KMS and evdev to the compositor. The Wayland
++      protocol lets the compositor send the input events directly
++      to the clients and lets the client send the damage event
++      directly to the compositor:
++    </para>
++    <figure>
++      <title>Wayland architecture diagram</title>
++      <mediaobjectco>
++      <imageobjectco>
++        <areaspec id="mapB" units="other" otherunits="imagemap">
++          <area id="areaB_1" linkends="wayland_flow_1" x_steal="#step_1"/>
++          <area id="areaB_2" linkends="wayland_flow_2" x_steal="#step_2"/>
++          <area id="areaB_3" linkends="wayland_flow_3" x_steal="#step_3"/>
++          <area id="areaB_4" linkends="wayland_flow_4" x_steal="#step_4"/>
++        </areaspec>
++        <imageobject>
++          <imagedata fileref="images/wayland-architecture.png" format="PNG" />
++        </imageobject>
++      </imageobjectco>
++      </mediaobjectco>
++    </figure>
++    <para>
++      <orderedlist>
++      <listitem id="wayland_flow_1">
++        <para>
++          The kernel gets an event and sends
++          it to the compositor. This
++          is similar to the X case, which is
++          great, since we get to reuse all the
++          input drivers in the kernel.
++        </para>
++      </listitem>
++      <listitem id="wayland_flow_2">
++        <para>
++          The compositor looks through its
++          scenegraph to determine which window
++          should receive the event. The
++          scenegraph corresponds to what's on
++          screen and the compositor
++          understands the transformations that
++          it may have applied to the elements
++          in the scenegraph. Thus, the
++          compositor can pick the right window
++          and transform the screen coordinates
++          to window-local coordinates, by
++          applying the inverse
++          transformations. The types of
++          transformation that can be applied
++          to a window is only restricted to
++          what the compositor can do, as long
++          as it can compute the inverse
++          transformation for the input events.
++        </para>
++      </listitem>
++      <listitem id="wayland_flow_3">
++        <para>
++          As in the X case, when the client
++          receives the event, it updates the
++          UI in response. But in the Wayland
++          case, the rendering happens in the
++          client, and the client just sends a
++          request to the compositor to
++          indicate the region that was
++          updated.
++        </para>
++      </listitem>
++      <listitem id="wayland_flow_4">
++        <para>
++          The compositor collects damage
++          requests from its clients and then
++          recomposites the screen. The
++          compositor can then directly issue
++          an ioctl to schedule a pageflip with
++          KMS.
++        </para>
++      </listitem>
++
++
++      </orderedlist>
++    </para>
++  </section>
++  <section id="sect-Wayland-Architecture-wayland_rendering">
++    <title>Wayland Rendering</title>
++    <para>
++      One of the details I left out in the above overview
++      is how clients actually render under Wayland. By
++      removing the X server from the picture we also
++      removed the mechanism by which X clients typically
++      render. But there's another mechanism that we're
++      already using with DRI2 under X: direct rendering.
++      With direct rendering, the client and the server
++      share a video memory buffer. The client links to a
++      rendering library such as OpenGL that knows how to
++      program the hardware and renders directly into the
++      buffer. The compositor in turn can take the buffer
++      and use it as a texture when it composites the
++      desktop. After the initial setup, the client only
++      needs to tell the compositor which buffer to use and
++      when and where it has rendered new content into it.
++    </para>
++
++    <para>
++      This leaves an application with two ways to update its window contents:
++    </para>
++    <para>
++      <orderedlist>
++      <listitem>
++        <para>
++          Render the new content into a new buffer and tell the compositor
++          to use that instead of the old buffer. The application can
++          allocate a new buffer every time it needs to update the window
++          contents or it can keep two (or more) buffers around and cycle
++          between them. The buffer management is entirely under
++          application control.
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          Render the new content into the buffer that it previously
++          told the compositor to to use. While it's possible to just
++          render directly into the buffer shared with the compositor,
++          this might race with the compositor. What can happen is that
++          repainting the window contents could be interrupted by the
++          compositor repainting the desktop. If the application gets
++          interrupted just after clearing the window but before
++          rendering the contents, the compositor will texture from a
++          blank buffer. The result is that the application window will
++          flicker between a blank window or half-rendered content. The
++          traditional way to avoid this is to render the new content
++          into a back buffer and then copy from there into the
++          compositor surface. The back buffer can be allocated on the
++          fly and just big enough to hold the new content, or the
++          application can keep a buffer around. Again, this is under
++          application control.
++        </para>
++      </listitem>
++      </orderedlist>
++    </para>
++    <para>
++      In either case, the application must tell the compositor
++      which area of the surface holds new contents. When the
++      application renders directly to the shared buffer, the
++      compositor needs to be noticed that there is new content.
++      But also when exchanging buffers, the compositor doesn't
++      assume anything changed, and needs a request from the
++      application before it will repaint the desktop. The idea
++      that even if an application passes a new buffer to the
++      compositor, only a small part of the buffer may be
++      different, like a blinking cursor or a spinner.
++    </para>
++  </section>
++  <section id="sect-Wayland-Architecture-wayland_hw_enabling">
++    <title>Hardware Enabling for Wayland</title>
++    <para>
++      Typically, hardware enabling includes modesetting/display
++      and EGL/GLES2. On top of that Wayland needs a way to share
++      buffers efficiently between processes. There are two sides
++      to that, the client side and the server side.
++    </para>
++    <para>
++      On the client side we've defined a Wayland EGL platform. In
++      the EGL model, that consists of the native types
++      (EGLNativeDisplayType, EGLNativeWindowType and
++      EGLNativePixmapType) and a way to create those types. In
++      other words, it's the glue code that binds the EGL stack and
++      its buffer sharing mechanism to the generic Wayland API. The
++      EGL stack is expected to provide an implementation of the
++      Wayland EGL platform. The full API is in the wayland-egl.h
++      header. The open source implementation in the mesa EGL stack
++      is in wayland-egl.c and platform_wayland.c.
++    </para>
++    <para>
++      Under the hood, the EGL stack is expected to define a
++      vendor-specific protocol extension that lets the client side
++      EGL stack communicate buffer details with the compositor in
++      order to share buffers. The point of the wayland-egl.h API
++      is to abstract that away and just let the client create an
++      EGLSurface for a Wayland surface and start rendering. The
++      open source stack uses the drm Wayland extension, which lets
++      the client discover the drm device to use and authenticate
++      and then share drm (GEM) buffers with the compositor.
++    </para>
++    <para>
++      The server side of Wayland is the compositor and core UX for
++      the vertical, typically integrating task switcher, app
++      launcher, lock screen in one monolithic application. The
++      server runs on top of a modesetting API (kernel modesetting,
++      OpenWF Display or similar) and composites the final UI using
++      a mix of EGL/GLES2 compositor and hardware overlays if
++      available. Enabling modesetting, EGL/GLES2 and overlays is
++      something that should be part of standard hardware bringup.
++      The extra requirement for Wayland enabling is the
++      EGL_WL_bind_wayland_display extension that lets the
++      compositor create an EGLImage from a generic Wayland shared
++      buffer. It's similar to the EGL_KHR_image_pixmap extension
++      to create an EGLImage from an X pixmap.
++    </para>
++    <para>
++      The extension has a setup step where you have to bind the
++      EGL display to a Wayland display. Then as the compositor
++      receives generic Wayland buffers from the clients (typically
++      when the client calls eglSwapBuffers), it will be able to
++      pass the struct wl_buffer pointer to eglCreateImageKHR as
++      the EGLClientBuffer argument and with EGL_WAYLAND_BUFFER_WL
++      as the target. This will create an EGLImage, which can then
++      be used by the compositor as a texture or passed to the
++      modesetting code to use as an overlay plane. Again, this is
++      implemented by the vendor specific protocol extension, which
++      on the server side will receive the driver specific details
++      about the shared buffer and turn that into an EGL image when
++      the user calls eglCreateImageKHR.
++    </para>
++  </section>
++</chapter>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2bdde62b38c85cc8dbebe36491ff59c71f295a25
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,16 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE authorgroup PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<authorgroup>
++  <author>
++    <firstname>Kristian</firstname>
++    <surname>Høgsberg</surname>
++    <affiliation>
++      <orgname>Intel Corporation</orgname>
++    </affiliation>
++    <email>krh@bitplanet.net</email>
++  </author>
++</authorgroup>
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..897673a0a5df3a8353f19857beeb5c61de9293bf
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,71 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE bookinfo PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<bookinfo id="book-Wayland-Wayland">
++  <title>Wayland</title>
++  <subtitle>The Wayland Protocol</subtitle>
++  <productname>Documentation</productname>
++  <productnumber>0.1</productnumber>
++  <edition>1</edition>
++  <pubsnumber>0</pubsnumber>
++  <abstract>
++    <para>
++      Wayland is a protocol for a compositor to talk to
++      its clients as well as a C library implementation of
++      that protocol. The compositor can be a standalone
++      display server running on Linux kernel modesetting
++      and evdev input devices, an X application, or a
++      Wayland client itself. The clients can be
++      traditional applications, X servers (rootless or
++      fullscreen) or other display servers.
++    </para>
++  </abstract>
++  <corpauthor>
++    <inlinemediaobject>
++      <imageobject>
++      <imagedata fileref="images/wayland.png" format="PNG" />
++      </imageobject>
++      <textobject>
++      <phrase>
++        Wayland logo
++      </phrase>
++      </textobject>
++    </inlinemediaobject>
++  </corpauthor>
++
++  <legalnotice lang="en-US">
++    <para>
++      Copyright <trademark class="copyright"></trademark> &YEAR; &HOLDER;
++    </para>
++
++      <para>
++        Permission is hereby granted, free of charge, to any person obtaining a
++        copy of this software and associated documentation files (the "Software"),
++        to deal in the Software without restriction, including without limitation
++        the rights to use, copy, modify, merge, publish, distribute, sublicense,
++        and/or sell copies of the Software, and to permit persons to whom the
++        Software is furnished to do so, subject to the following conditions:
++      </para>
++
++      <para>
++        The above copyright notice and this permission notice (including the next
++        paragraph) shall be included in all copies or substantial portions of the
++        Software.
++      </para>
++
++      <para>
++        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++        THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++        FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++        DEALINGS IN THE SOFTWARE.
++      </para>
++  </legalnotice>
++
++
++  <xi:include href="Author_Group.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++</bookinfo>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..19bf3e9572a34cc3634c32ba8ca4ea4b253c4b8b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,92 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++  <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++  <!ENTITY doxygen SYSTEM "ClientAPI.xml">
++%BOOK_ENTITIES;
++]>
++<appendix id="sect-Library-Client">
++  <title>Client API</title>
++  <section><title>Introduction</title>
++  <para>
++    The open-source reference implementation of Wayland protocol is
++    split in two C libraries, libwayland-client and <link
++    linkend="sect-Library-Server">libwayland-server</link>. Their main
++    responsibility is to handle the Inter-process communication
++    (<emphasis>IPC</emphasis>) with each other, therefore guaranteeing
++    the protocol objects marshaling and messages synchronization.
++  </para>
++  <para>
++    A client uses libwayland-client to communicate with one or more
++    wayland servers. A <link
++    linkend="Client-classwl__display">wl_display</link> object is
++    created and manages each open connection to a server. At least one
++    <link linkend="Client-classwl__event__queue">wl_event_queue</link>
++    object is created for each wl_display, this holds events as they
++    are received from the server until they can be
++    processed. Multi-threading is supported by creating an additional
++    wl_event_queue for each additional thread, each object can have
++    it's events placed in a particular queue, so potentially a
++    different thread could be made to handle the events for each
++    object created.
++  </para>
++  <para>
++    Though some convenience functions are provided, libwayland-client
++    is designed to allow the calling code to wait for events, so that
++    different polling mechanisms can be used. A file descriptor is
++    provided, when it becomes ready for reading the calling code can
++    ask libwayland-client to read the available events from it into
++    the wl_event_queue objects.
++  </para>
++  <para>
++    The library only provides low-level access to the wayland objects.
++    Each object created by the client is represented by a <link
++    linkend="Client-classwl__proxy">wl_proxy</link> object that this
++    library creates. This includes the id that is actually
++    communicated over the socket to the server, a void* data pointer
++    that is intended to point at a client's representation of the
++    object, and a pointer to a static <link
++    linkend="Client-structwl__interface">wl_interface</link> object,
++    which is generated from the xml and identifies the object's class
++    and can be used for introspection into the messages and events.
++  </para>
++  <para>
++    Messages are sent by calling wl_proxy_marshal. This will write a
++    message to the socket, by using the message id and the
++    wl_interface to identify the types of each argument and convert
++    them into stream format.  Most software will call type-safe
++    wrappers generated from the xml description of the <link
++    linkend="appe-Wayland-Protocol">Wayland protocols</link>. For
++    instance the C header file generated from the xml defines the
++    following inline function to transmit the <link
++    linkend="protocol-spec-wl_surface-request-attach">wl_surface::attach</link>
++    message:
++  </para>
++  <programlisting>static inline void
++wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
++{
++  wl_proxy_marshal((struct wl_proxy *) wl_surface, WL_SURFACE_ATTACH, buffer, x, y);
++}</programlisting>
++  <para>
++    Events (messages from the server) are handled by calling a
++    "dispatcher" callback the client stores in the wl_proxy for each
++    event. A language binding for a string-based interpreter, such as
++    CPython, might have a dispatcher that uses the event name from the
++    wl_interface to identify the function to call. The default
++    dispatcher uses the message id number to index an array of
++    functions pointers, called a wl_listener, and the wl_interface to
++    convert data from the stream into arguments to the function. The
++    C header file generated from the xml defines a per-class structure
++    that forces the function pointers to be of the correct type, for
++    instance the <link
++    linkend="protocol-spec-wl_surface-event-enter">wl_surface::enter</link>
++    event defines this pointer in the wl_surface_listener object:
++  </para>
++  <programlisting>struct wl_surface_listener {
++  void (*enter)(void *data, struct wl_surface *, struct wl_output *);
++  ...
++}</programlisting>
++  <para>
++  </para>
++  </section>
++  &doxygen;
++</appendix>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7a7bdaa06c57b1373b05f15ceafffdf3b4ee12f9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,128 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Compositors">
++  <title>Types of Compositors</title>
++
++  <para>
++    Compositors come in different types, depending on which
++    role they play in the overall architecture of the OS.
++    For instance, a
++    <link linkend="sect-Compositors-System-Compositor">system compositor</link>
++    can be used for booting the system, handling multiple user switching, a
++    possible console terminal emulator and so forth. A different compositor, a
++    <link linkend="sect-Compositors-Session-Compositor">session compositor</link>
++    would provide the actual desktop environment. There are many ways for
++    different types of compositors to co-exist.
++  </para>
++  <para>
++    In this section, we introduce three types of Wayland compositors relying
++    on <link linkend="sect-Library-Server">libwayland-server</link>.
++  </para>
++
++  <section id="sect-Compositors-System-Compositor">
++    <title>System Compositor</title>
++    <para>
++      A system compositor can run from early boot until shutdown.
++      It effectively replaces the kernel vt system, and can tie in
++      with the systems graphical boot setup and multiseat support.
++    </para>
++    <para>
++      A system compositor can host different types of session
++      compositors, and let us switch between multiple sessions
++      (fast user switching, or secure/personal desktop switching).
++    </para>
++    <para>
++      A linux implementation of a system compositor will typically
++      use libudev, egl, kms, evdev and cairo.
++    </para>
++    <para>
++      For fullscreen clients, the system compositor can reprogram the
++      video scanout address to read directly from the client provided
++      buffer.
++    </para>
++  </section>
++  <section id="sect-Compositors-Session-Compositor">
++    <title>Session Compositor</title>
++    <para>
++      A session compositor is responsible for a single user session.
++      If a system compositor is present, the session compositor will
++      run nested under the system compositor. Nesting is feasible because
++      the protocol is asynchronous; roundtrips would be too expensive
++      when nesting is involved. If no system compositor is present, a
++      session compositor can run directly on the hardware.
++     </para>
++     <para>
++      X applications can continue working under a session compositor
++      by means of a root-less X server that is activated on demand.
++     </para>
++    <para>
++       Possible examples for session compositors include
++      <itemizedlist>
++      <listitem>
++        <para>
++          gnome-shell
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          moblin
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          kwin
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          kmscon
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          rdp session
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          Weston with X11 or Wayland backend is a session compositor nested
++          in another session compositor.
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          fullscreen X session under Wayland
++        </para>
++      </listitem>
++      </itemizedlist>
++    </para>
++  </section>
++  <section id="sect-Compositors-Embedding-Compositor">
++    <title>Embedding Compositor</title>
++    <para>
++      X11 lets clients embed windows from other clients, or lets clients
++      copy pixmap contents rendered by another client into their window.
++      This is often used for applets in a panel, browser plugins and similar.
++      Wayland doesn't directly allow this, but clients can communicate GEM
++      buffer names out-of-band, for example, using D-Bus, or command line
++      arguments when the panel launches the applet.  Another option is to
++      use a nested Wayland instance.  For this, the Wayland server will have
++      to be a library that the host application links to.  The host
++      application will then pass the Wayland server socket name to the
++      embedded application, and will need to implement the Wayland
++      compositor interface.  The host application composites the client
++      surfaces as part of it's window, that is, in the web page or in the
++      panel.  The benefit of nesting the Wayland server is that it provides
++      the requests the embedded client needs to inform the host about buffer
++      updates and a mechanism for forwarding input events from the host
++      application.
++    </para>
++    <para>
++      An example for this kind of setup is firefox embedding the flash
++      player as a kind of special-purpose compositor.
++    </para>
++  </section>
++</chapter>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..46fda2becd8a50c259ce0ab06e6a62f74c162380
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,28 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++
++<preface>
++  <title>Preface</title>
++
++  <para>
++  This document describes the (i) Wayland architecture, (ii) Wayland model of
++  operation and (iii) its library API. Also, the Wayland protocol specification is shown
++  in the Appendix. This document is aimed primarily at Wayland developers and
++  those looking to program with it; it does not cover application development.
++  </para>
++  <para>
++  There have been many contributors to this document and since this is only the
++  first edition many errors are expected to be found. We appreciate
++  corrections.
++  </para>
++  <literallayout>
++Yours,
++
++      the Wayland open-source community
++      November 2012
++  </literallayout>
++</preface>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..276db2daca8ae5265eb5a8cc6d827325c74d5938
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,116 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Introduction">
++  <title>Introduction</title>
++  <section id="sect-Motivation">
++    <title>Motivation</title>
++    <para>
++      Most Linux and Unix-based systems rely on the X Window System (or
++      simply <emphasis>X</emphasis>) as the low-level protocol for building
++      bitmap graphics interfaces. On these systems, the X stack has grown to
++      encompass functionality arguably belonging in client libraries,
++      helper libraries, or the host operating system kernel.  Support for
++      things like PCI resource management, display configuration management,
++      direct rendering, and memory management has been integrated into the X
++      stack, imposing limitations like limited support for standalone
++      applications, duplication in other projects (e.g. the Linux fb layer
++      or the DirectFB project), and high levels of complexity for systems
++      combining multiple elements (for example radeon memory map handling
++      between the fb driver and X driver, or VT switching).
++    </para>
++    <para>
++      Moreover, X has grown to incorporate modern features like offscreen
++      rendering and scene composition, but subject to the limitations of the
++      X architecture.  For example, the X implementation of composition adds
++      additional context switches and makes things like input redirection
++      difficult.
++    </para>
++    <mediaobject>
++      <imageobject>
++      <imagedata fileref="images/x-architecture.png" format="PNG" />
++      </imageobject>
++      <textobject>
++      <phrase>
++        X architecture diagram
++      </phrase>
++      </textobject>
++    </mediaobject>
++    <para>
++      The diagram above illustrates the central role of the X server and
++      compositor in operations, and the steps required to get contents on to
++      the screen.
++    </para>
++    <para>
++      Over time, X developers came to understand the shortcomings of this
++      approach and worked to split things up.  Over the past several years,
++      a lot of functionality has moved out of the X server and into
++      client-side libraries or kernel drivers. One of the first components
++      to move out was font rendering, with freetype and fontconfig providing
++      an alternative to the core X fonts.  Direct rendering OpenGL as a
++      graphics driver in a client side library went through some iterations,
++      ending up as DRI2, which abstracted most of the direct rendering
++      buffer management from client code. Then cairo came along and provided
++      a modern 2D rendering library independent of X, and compositing
++      managers took over control of the rendering of the desktop as toolkits
++      like GTK+ and Qt moved away from using X APIs for rendering. Recently,
++      memory and display management have moved to the Linux kernel, further
++      reducing the scope of X and its driver stack.  The end result is a
++      highly modular graphics stack.
++    </para>
++
++  </section>
++
++  <section id="sect-Compositing-manager-display-server">
++    <title>The compositing manager as the display server</title>
++    <para>
++      Wayland is a new display server and compositing protocol, and Weston
++      is the implementation of this protocol which builds on top of all the
++      components above. We are trying to distill out the functionality in
++      the X server that is still used by the modern Linux desktop. This
++      turns out to be not a whole lot. Applications can allocate their own
++      off-screen buffers and render their window contents directly, using
++      hardware accelerated libraries like libGL, or high quality software
++      implementations like those found in Cairo. In the end, what’s needed
++      is a way to present the resulting window surface for display, and a
++      way to receive and arbitrate input among multiple clients. This is
++      what Wayland provides, by piecing together the components already in
++      the eco-system in a slightly different way.
++    </para>
++    <para>
++      X will always be relevant, in the same way Fortran compilers and VRML
++      browsers are, but it’s time that we think about moving it out of the
++      critical path and provide it as an optional component for legacy
++      applications.
++    </para>
++    <para>
++      Overall, the philosophy of Wayland is to provide clients with a way to
++      manage windows and how their contents is displayed.  Rendering is left
++      to clients, and system wide memory management interfaces are used to
++      pass buffer handles between clients and the compositing manager.
++    </para>
++    <mediaobject>
++      <imageobject>
++      <imagedata fileref="images/wayland-architecture.png" format="PNG" />
++      </imageobject>
++      <textobject>
++      <phrase>
++        Wayland architecture diagram
++      </phrase>
++      </textobject>
++    </mediaobject>
++    <para>
++      The figure above illustrates how Wayland clients interact with a
++      Wayland server.  Note that window management and composition are
++      handled entirely in the server, significantly reducing complexity
++      while marginally improving performance through reduced context
++      switching.  The resulting system is easier to build and extend than a
++      similar X system, because often changes need only be made in one
++      place.  Or in the case of protocol extensions, two (rather than 3 or 4
++      in the X case where window management and/or composition handling may
++      also need to be updated).
++    </para>
++  </section>
++</chapter>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..17c6ebffa2710c1e1dfa582b386fc7bc659356ad
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,20 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
++"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++
++<preface>
++  <title>Acknowledgments</title>
++
++  <para>
++  TODO: Kristian has to fill up this with one or two paragraphs and a small
++  "thank you": http://en.wikipedia.org/wiki/Preface
++  </para>
++  <literallayout>
++Best,
++
++      Kristian Høgsberg
++  </literallayout>
++</preface>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..57d883570744022d8a0a3f913dd25414d8df2276
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,588 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-Protocol">
++  <title>Wayland Protocol and Model of Operation</title>
++  <section id="sect-Protocol-Basic-Principles">
++    <title>Basic Principles</title>
++    <para>
++      The Wayland protocol is an asynchronous object oriented protocol.  All
++      requests are method invocations on some object.  The requests include
++      an object ID that uniquely identifies an object on the server.  Each
++      object implements an interface and the requests include an opcode that
++      identifies which method in the interface to invoke.
++    </para>
++    <para>
++      The protocol is message-based.  A message sent by a client to the server
++      is called request.  A message from the server to a client is called event.
++      A message has a number of arguments, each of which has a certain type (see
++      <xref linkend="sect-Protocol-Wire-Format"/> for a list of argument types).
++    </para>
++    <para>
++      Additionally, the protocol can specify <type>enum</type>s which associate
++      names to specific numeric enumeration values.  These are primarily just
++      descriptive in nature: at the wire format level enums are just integers.
++      But they also serve a secondary purpose to enhance type safety or
++      otherwise add context for use in language bindings or other such code.
++      This latter usage is only supported so long as code written before these
++      attributes were introduced still works after; in other words, adding an
++      enum should not break API, otherwise it puts backwards compatibility at
++      risk.
++    </para>
++    <para>
++      <type>enum</type>s can be defined as just a set of integers, or as
++      bitfields.  This is specified via the <type>bitfield</type> boolean
++      attribute in the <type>enum</type> definition.  If this attribute is true,
++      the enum is intended to be accessed primarily using bitwise operations,
++      for example when arbitrarily many choices of the enum can be ORed
++      together; if it is false, or the attribute is omitted, then the enum
++      arguments are a just a sequence of numerical values.
++    </para>
++    <para>
++      The <type>enum</type> attribute can be used on either <type>uint</type>
++      or <type>int</type> arguments, however if the <type>enum</type> is
++      defined as a <type>bitfield</type>, it can only be used on
++      <type>uint</type> args.
++    </para>
++    <para>
++      The server sends back events to the client, each event is emitted from
++      an object.  Events can be error conditions.  The event includes the
++      object ID and the event opcode, from which the client can determine
++      the type of event.  Events are generated both in response to requests
++      (in which case the request and the event constitutes a round trip) or
++      spontaneously when the server state changes.
++    </para>
++    <para>
++      <itemizedlist>
++      <listitem>
++        <para>
++          State is broadcast on connect, events are sent
++          out when state changes. Clients must listen for
++          these changes and cache the state.
++          There is no need (or mechanism) to query server state.
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          The server will broadcast the presence of a number of global objects,
++          which in turn will broadcast their current state.
++        </para>
++      </listitem>
++      </itemizedlist>
++    </para>
++  </section>
++  <section id="sect-Protocol-Code-Generation">
++    <title>Code Generation</title>
++    <para>
++      The interfaces, requests and events are defined in
++      <filename>protocol/wayland.xml</filename>.
++      This xml is used to generate the function prototypes that can be used by
++      clients and compositors.
++    </para>
++    <para>
++      The protocol entry points are generated as inline functions which just
++      wrap the <function>wl_proxy_*</function> functions.  The inline functions aren't
++      part of the library ABI and language bindings should generate their
++      own stubs for the protocol entry points from the xml.
++    </para>
++  </section>
++  <section id="sect-Protocol-Wire-Format">
++    <title>Wire Format</title>
++    <para>
++      The protocol is sent over a UNIX domain stream socket, where the endpoint
++      usually is named <systemitem class="service">wayland-0</systemitem>
++      (although it can be changed via <emphasis>WAYLAND_DISPLAY</emphasis>
++      in the environment). Beginning in Wayland 1.15, implementations can
++      optionally support server socket endpoints located at arbitrary
++      locations in the filesystem by setting <emphasis>WAYLAND_DISPLAY</emphasis>
++      to the absolute path at which the server endpoint listens.
++    </para>
++    <para>
++      Every message is structured as 32-bit words; values are represented in the
++      host's byte-order.  The message header has 2 words in it:
++      <itemizedlist>
++      <listitem>
++        <para>
++          The first word is the sender's object ID (32-bit).
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          The second has 2 parts of 16-bit.  The upper 16-bits are the message
++          size in bytes, starting at the header (i.e. it has a minimum value of 8).The lower is the request/event opcode.
++        </para>
++      </listitem>
++      </itemizedlist>
++      The payload describes the request/event arguments.  Every argument is always
++      aligned to 32-bits. Where padding is required, the value of padding bytes is
++      undefined. There is no prefix that describes the type, but it is
++      inferred implicitly from the xml specification.
++    </para>
++    <para>
++
++      The representation of argument types are as follows:
++      <variablelist>
++      <varlistentry>
++        <term>int</term>
++        <term>uint</term>
++        <listitem>
++          <para>
++            The value is the 32-bit value of the signed/unsigned
++            int.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>fixed</term>
++        <listitem>
++          <para>
++            Signed 24.8 decimal numbers. It is a signed decimal type which
++            offers a sign bit, 23 bits of integer precision and 8 bits of
++            decimal precision. This is exposed as an opaque struct with
++            conversion helpers to and from double and int on the C API side.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>string</term>
++        <listitem>
++          <para>
++            Starts with an unsigned 32-bit length (including null terminator),
++            followed by the string contents, including terminating null byte,
++            then padding to a 32-bit boundary. A null value is represented
++            with a length of 0.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>object</term>
++        <listitem>
++          <para>
++            32-bit object ID. A null value is represented with an ID of 0.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>new_id</term>
++        <listitem>
++          <para>
++            The 32-bit object ID.  Generally, the interface used for the new
++            object is inferred from the xml, but in the case where it's not
++            specified, a new_id is preceded by a <code>string</code> specifying
++            the interface name, and a <code>uint</code> specifying the version.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>array</term>
++        <listitem>
++          <para>
++            Starts with 32-bit array size in bytes, followed by the array
++            contents verbatim, and finally padding to a 32-bit boundary.
++          </para>
++        </listitem>
++      </varlistentry>
++      <varlistentry>
++        <term>fd</term>
++        <listitem>
++          <para>
++            The file descriptor is not stored in the message buffer, but in
++            the ancillary data of the UNIX domain socket message (msg_control).
++          </para>
++        </listitem>
++      </varlistentry>
++      </variablelist>
++    </para>
++    <para>
++      The protocol does not specify the exact position of the ancillary data
++      in the stream, except that the order of file descriptors is the same as
++      the order of messages and <code>fd</code> arguments within messages on
++      the wire.
++    </para>
++    <para>
++      In particular, it means that any byte of the stream, even the message
++      header, may carry the ancillary data with file descriptors.
++    </para>
++    <para>
++      Clients and compositors should queue incoming data until they have
++      whole messages to process, as file descriptors may arrive earlier
++      or later than the corresponding data bytes.
++    </para>
++  </section>
++  <xi:include href="ProtocolInterfaces.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++  <section id="sect-Protocol-Versioning">
++    <title>Versioning</title>
++    <para>
++      Every interface is versioned and every protocol object implements a
++      particular version of its interface.  For global objects, the maximum
++      version supported by the server is advertised with the global and the
++      actual version of the created protocol object is determined by the
++      version argument passed to wl_registry.bind().  For objects that are
++      not globals, their version is inferred from the object that created
++      them.
++    </para>
++    <para>
++      In order to keep things sane, this has a few implications for
++      interface versions:
++      <itemizedlist>
++      <listitem>
++        <para>
++          The object creation hierarchy must be a tree.  Otherwise,
++          inferring object versions from the parent object becomes a much
++          more difficult to properly track.
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          When the version of an interface increases, so does the version
++          of its parent (recursively until you get to a global interface)
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          A global interface's version number acts like a counter for all
++          of its child interfaces.  Whenever a child interface gets
++          modified, the global parent's interface version number also
++          increases (see above).  The child interface then takes on the
++          same version number as the new version of its parent global
++          interface.
++        </para>
++      </listitem>
++      </itemizedlist>
++    </para>
++    <para>
++      To illustrate the above, consider the wl_compositor interface.  It
++      has two children, wl_surface and wl_region.  As of wayland version
++      1.2, wl_surface and wl_compositor are both at version 3.  If
++      something is added to the wl_region interface, both wl_region and
++      wl_compositor will get bumpped to version 4.  If, afterwards,
++      wl_surface is changed, both wl_compositor and wl_surface will be at
++      version 5.  In this way the global interface version is used as a
++      sort of "counter" for all of its child interfaces.  This makes it
++      very simple to know the version of the child given the version of its
++      parent.  The child is at the highest possible interface version that
++      is less than or equal to its parent's version.
++    </para>
++    <para>
++      It is worth noting a particular exception to the above versioning
++      scheme.  The wl_display (and, by extension, wl_registry) interface
++      cannot change because it is the core protocol object and its version
++      is never advertised nor is there a mechanism to request a different
++      version.
++    </para>
++  </section>
++  <section id="sect-Protocol-Connect-Time">
++    <title>Connect Time</title>
++    <para>
++      There is no fixed connection setup information, the server emits
++      multiple events at connect time, to indicate the presence and
++      properties of global objects: outputs, compositor, input devices.
++    </para>
++  </section>
++  <section id="sect-Protocol-Security-and-Authentication">
++    <title>Security and Authentication</title>
++    <para>
++      <itemizedlist>
++      <listitem>
++        <para>
++          mostly about access to underlying buffers, need new drm auth
++          mechanism (the grant-to ioctl idea), need to check the cmd stream?
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          getting the server socket depends on the compositor type, could
++          be a system wide name, through fd passing on the session dbus.
++          or the client is forked by the compositor and the fd is
++          already opened.
++        </para>
++      </listitem>
++      </itemizedlist>
++    </para>
++  </section>
++  <section id="sect-Protocol-Creating-Objects">
++    <title>Creating Objects</title>
++    <para>
++      Each object has a unique ID.  The IDs are allocated by the entity
++      creating the object (either client or server).  IDs allocated by the
++      client are in the range [1, 0xfeffffff] while IDs allocated by the
++      server are in the range [0xff000000, 0xffffffff].  The 0 ID is
++      reserved to represent a null or non-existent object.
++
++      For efficiency purposes, the IDs are densely packed in the sense that
++      the ID N will not be used until N-1 has been used.  Any ID allocation
++      algorithm that does not maintain this property is incompatible with
++      the implementation in libwayland.
++    </para>
++  </section>
++  <section id="sect-Protocol-Compositor">
++    <title>Compositor</title>
++    <para>
++      The compositor is a global object, advertised at connect time.
++    </para>
++    <para>
++      See <xref linkend="protocol-spec-wl_compositor"/> for the
++      protocol description.
++    </para>
++  </section>
++  <section id="sect-Protocol-Surface">
++    <title>Surfaces</title>
++    <para>
++      A surface manages a rectangular grid of pixels that clients create
++      for displaying their content to the screen.  Clients don't know
++      the global position of their surfaces, and cannot access other
++      clients' surfaces.
++    </para>
++    <para>
++      Once the client has finished writing pixels, it 'commits' the
++      buffer; this permits the compositor to access the buffer and read
++      the pixels.  When the compositor is finished, it releases the
++      buffer back to the client.
++    </para>
++    <para>
++      See <xref linkend="protocol-spec-wl_surface"/> for the protocol
++      description.
++    </para>
++  </section>
++  <section id="sect-Protocol-Input">
++    <title>Input</title>
++    <para>
++      A seat represents a group of input devices including mice,
++      keyboards and touchscreens. It has a keyboard and pointer
++      focus. Seats are global objects. Pointer events are delivered
++      in surface-local coordinates.
++    </para>
++    <para>
++      The compositor maintains an implicit grab when a button is
++      pressed, to ensure that the corresponding button release
++      event gets delivered to the same surface. But there is no way
++      for clients to take an explicit grab. Instead, surfaces can
++      be mapped as 'popup', which combines transient window semantics
++      with a pointer grab.
++    </para>
++    <para>
++      To avoid race conditions, input events that are likely to
++      trigger further requests (such as button presses, key events,
++      pointer motions) carry serial numbers, and requests such as
++      wl_surface.set_popup require that the serial number of the
++      triggering event is specified. The server maintains a
++      monotonically increasing counter for these serial numbers.
++    </para>
++    <para>
++      Input events also carry timestamps with millisecond granularity.
++      Their base is undefined, so they can't be compared against
++      system time (as obtained with clock_gettime or gettimeofday).
++      They can be compared with each other though, and for instance
++      be used to identify sequences of button presses as double
++      or triple clicks.
++    </para>
++    <para>
++      See <xref linkend="protocol-spec-wl_seat"/> for the
++      protocol description.
++    </para>
++    <para>
++      Talk about:
++
++      <itemizedlist>
++      <listitem>
++        <para>
++          keyboard map, change events
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          xkb on Wayland
++        </para>
++      </listitem>
++      <listitem>
++        <para>
++          multi pointer Wayland
++        </para>
++      </listitem>
++      </itemizedlist>
++    </para>
++    <para>
++      A surface can change the pointer image when the surface is the pointer
++      focus of the input device.  Wayland doesn't automatically change the
++      pointer image when a pointer enters a surface, but expects the
++      application to set the cursor it wants in response to the pointer
++      focus and motion events.  The rationale is that a client has to manage
++      changing pointer images for UI elements within the surface in response
++      to motion events anyway, so we'll make that the only mechanism for
++      setting or changing the pointer image.  If the server receives a request
++      to set the pointer image after the surface loses pointer focus, the
++      request is ignored.  To the client this will look like it successfully
++      set the pointer image.
++    </para>
++    <para>
++      Setting the pointer image to NULL causes the cursor to be hidden.
++    </para>
++    <para>
++      The compositor will revert the pointer image back to a default image
++      when no surface has the pointer focus for that device.
++    </para>
++    <para>
++      What if the pointer moves from one window which has set a special
++      pointer image to a surface that doesn't set an image in response to
++      the motion event?  The new surface will be stuck with the special
++      pointer image.  We can't just revert the pointer image on leaving a
++      surface, since if we immediately enter a surface that sets a different
++      image, the image will flicker.  If a client does not set a pointer image
++      when the pointer enters a surface, the pointer stays with the image set
++      by the last surface that changed it, possibly even hidden.  Such a client
++      is likely just broken.
++    </para>
++  </section>
++  <section id="sect-Protocol-Output">
++    <title>Output</title>
++    <para>
++      An output is a global object, advertised at connect time or as it
++      comes and goes.
++    </para>
++    <para>
++      See <xref linkend="protocol-spec-wl_output"/> for the protocol
++      description.
++    </para>
++    <para>
++    </para>
++    <itemizedlist>
++      <listitem>
++      <para>
++        laid out in a big (compositor) coordinate system
++      </para>
++      </listitem>
++      <listitem>
++      <para>
++        basically xrandr over Wayland
++      </para>
++      </listitem>
++      <listitem>
++      <para>
++        geometry needs position in compositor coordinate system
++      </para>
++      </listitem>
++      <listitem>
++      <para>
++        events to advertise available modes, requests to move and change
++        modes
++      </para>
++      </listitem>
++    </itemizedlist>
++  </section>
++  <section id="sect-Protocol-data-sharing">
++    <title>Data sharing between clients</title>
++    <para>
++      The Wayland protocol provides clients a mechanism for sharing
++      data that allows the implementation of copy-paste and
++      drag-and-drop. The client providing the data creates a
++      <function>wl_data_source</function> object and the clients
++      obtaining the data will see it as <function>wl_data_offer</function>
++      object. This interface allows the clients to agree on a mutually
++      supported mime type and transfer the data via a file descriptor
++      that is passed through the protocol.
++    </para>
++    <para>
++      The next section explains the negotiation between data source and
++      data offer objects. <xref linkend="sect-Protocol-data-sharing-devices"/>
++      explains how these objects are created and passed to different
++      clients using the <function>wl_data_device</function> interface
++      that implements copy-paste and drag-and-drop support.
++    </para>
++    <para>
++      See <xref linkend="protocol-spec-wl_data_offer"/>,
++      <xref linkend="protocol-spec-wl_data_source"/>,
++      <xref linkend="protocol-spec-wl_data_device"/> and
++      <xref linkend="protocol-spec-wl_data_device_manager"/> for
++      protocol descriptions.
++    </para>
++    <para>
++      MIME is defined in RFC's 2045-2049. A
++      <ulink url="https://www.iana.org/assignments/media-types/media-types.xhtml">
++      registry of MIME types</ulink> is maintained by the Internet Assigned
++      Numbers Authority (IANA).
++    </para>
++    <section>
++      <title>Data negotiation</title>
++      <para>
++      A client providing data to other clients will create a <function>wl_data_source</function>
++      object and advertise the mime types for the formats it supports for
++      that data through the <function>wl_data_source.offer</function>
++      request. On the receiving end, the data offer object will generate one
++      <function>wl_data_offer.offer</function> event for each supported mime
++      type.
++      </para>
++      <para>
++      The actual data transfer happens when the receiving client sends a
++      <function>wl_data_offer.receive</function> request. This request takes
++      a mime type and a file descriptor as arguments. This request will generate a
++      <function>wl_data_source.send</function> event on the sending client
++      with the same arguments, and the latter client is expected to write its
++      data to the given file descriptor using the chosen mime type.
++      </para>
++    </section>
++    <section id="sect-Protocol-data-sharing-devices">
++      <title>Data devices</title>
++      <para>
++      Data devices glue data sources and offers together. A data device is
++      associated with a <function>wl_seat</function> and is obtained by the clients using the
++      <function>wl_data_device_manager</function> factory object, which is also responsible for
++      creating data sources.
++      </para>
++      <para>
++      Clients are informed of new data offers through the
++      <function>wl_data_device.data_offer</function> event. After this
++      event is generated the data offer will advertise the available mime
++      types. New data offers are introduced prior to their use for
++      copy-paste or drag-and-drop.
++      </para>
++      <section>
++      <title>Selection</title>
++      <para>
++        Each data device has a selection data source. Clients create a data
++        source object using the device manager and may set it as the
++        current selection for a given data device. Whenever the current
++        selection changes, the client with keyboard focus receives a
++        <function>wl_data_device.selection</function> event. This event is
++        also generated on a client immediately before it receives keyboard
++        focus.
++      </para>
++      <para>
++        The data offer is introduced with
++        <function>wl_data_device.data_offer</function> event before the
++        selection event.
++      </para>
++      </section>
++      <section>
++      <title>Drag and Drop</title>
++      <para>
++        A drag-and-drop operation is started using the
++        <function>wl_data_device.start_drag</function> request. This
++        requests causes a pointer grab that will generate enter, motion and
++        leave events on the data device. A data source is supplied as
++        argument to start_drag, and data offers associated with it are
++        supplied to clients surfaces under the pointer in the
++        <function>wl_data_device.enter</function> event. The data offer
++        is introduced to the client prior to the enter event with the
++        <function>wl_data_device.data_offer</function> event.
++      </para>
++      <para>
++        Clients are expected to provide feedback to the data sending client
++        by calling the <function>wl_data_offer.accept</function> request with
++        a mime type it accepts. If none of the advertised mime types is
++        supported by the receiving client, it should supply NULL to the
++        accept request. The accept request causes the sending client to
++        receive a <function>wl_data_source.target</function> event with the
++        chosen mime type.
++      </para>
++      <para>
++        When the drag ends, the receiving client receives a
++        <function>wl_data_device.drop</function> event at which it is expected
++        to transfer the data using the
++        <function>wl_data_offer.receive</function> request.
++      </para>
++      </section>
++    </section>
++  </section>
++</chapter>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2c540fecf23f39c3db7d76fc62440b9a2a3383c2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,7 @@@
++<revhistory>
++  <revision>
++    <revnumber>1-0</revnumber>
++    <authorinitials>krh</authorinitials>
++    <revremark>Initial version</revremark>
++  </revision>
++</revhistory>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2333b1a4fba61d145a0db34c73db2a799847f672
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,49 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++  <!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++  <!ENTITY doxygen SYSTEM "ServerAPI.xml">
++%BOOK_ENTITIES;
++]>
++<appendix id="sect-Library-Server">
++  <title>Server API</title>
++  <section><title>Introduction</title>
++  <para>
++    The open-source reference implementation of Wayland protocol is
++    split in two C libraries, <link
++    linkend="sect-Library-Client">libwayland-client</link> and
++    libwayland-server. Their main responsibility is to handle the
++    Inter-process communication (<emphasis>IPC</emphasis>) with each
++    other, therefore guaranteeing the protocol objects marshaling and
++    messages synchronization.
++  </para>
++  <para>
++    The server library is designed to work much like libwayland-client,
++    although it is considerably complicated due to the server needing
++    to support multiple versions of the protocol. It is best to learn
++    libwayland-client first.
++  </para>
++  <para>
++    Each open socket to a client is represented by a <link
++    linkend="Server-structwl__client">wl_client</link>.  The equivalent
++    of the <link linkend="Client-classwl__proxy">wl_proxy</link> that
++    libwayland-client uses to represent an object is <link
++    linkend="Server-structwl__resource">wl_resource</link> for
++    client-created objects, and <link
++    linkend="Server-structwl__global">wl_global</link> for objects
++    created by the server.
++  </para>
++  <para>
++    Often a server is also a client for another Wayland server, and
++    thus must link with both libwayland-client and libwayland-server.
++    This produces some type name conflicts (such as the <link
++    linkend="Client-classwl__display">client wl_display</link> and
++    <link linkend="Server-structwl__display">server wl_display</link>,
++    but the duplicate-but-not-the-same types are opaque, and accessed
++    only inside the correct library where it came from. Naturally that
++    means that the program writer needs to always know if a pointer to
++    a wl_display is for the server or client side and use the
++    corresponding functions.
++  </para>
++  </section>
++  &doxygen;
++</appendix>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..da18a952e9848065095ce5dc87b0dc3c5b00de6d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++<!ENTITY PRODUCT "Documentation">
++<!ENTITY BOOKID "Wayland">
++<!ENTITY YEAR "2012">
++<!ENTITY HOLDER "Kristian Høgsberg, Intel Corporation">
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0457c15cba145aae438695d3a884b3758d87b721
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,18 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<book>
++  <xi:include href="Book_Info.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Foreword.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Preface.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Introduction.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Compositors.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Architecture.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Protocol.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Xwayland.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="ProtocolSpec.xml" xmlns:xi="http://www.w3.org/2001/XInclude" />
++  <xi:include href="Client.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++  <xi:include href="Server.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
++</book>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..79155598722d9699a8de5bf3cb7feb22ea890891
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,170 @@@
++<?xml version='1.0' encoding='utf-8' ?>
++<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
++<!ENTITY % BOOK_ENTITIES SYSTEM "Wayland.ent">
++%BOOK_ENTITIES;
++]>
++<chapter id="chap-X11-Application-Support">
++  <title>X11 Application Support</title>
++  <section id="sect-X11-Application-Support-introduction">
++    <title>Introduction</title>
++    <para>
++      Being able to run existing X11 applications is crucial for the adoption
++      of Wayland, especially on desktops, as there will always be X11
++      applications that have not been or cannot be converted into Wayland
++      applications, and throwing them all away would be prohibitive.
++      Therefore a Wayland compositor often needs to support running X11
++      applications.
++    </para>
++    <para>
++      X11 and Wayland are different enough that there is no "simple" way to
++      translate between them. Most of X11 is uninteresting to a Wayland
++      compositor. That, combined with the gigantic implementation effort needed
++      to support X11, makes it intractable to just write X11 support directly in
++      a Wayland compositor. The implementation would be nothing short of a
++      real X11 server.
++    </para>
++    <para>
++      Therefore, Wayland compositors should use Xwayland, the X11 server that
++      lives in the Xorg server source code repository and shares most of the
++      implementation with the Xorg server. Xwayland is a complete X11 server,
++      just like Xorg is, but instead of driving the displays and opening input
++      devices, it acts as a Wayland client. The rest of this chapter talks
++      about how Xwayland works.
++    </para>
++    <para>
++      For integration and architecture reasons, while Xwayland is a Wayland
++      client of the Wayland compositor, the Wayland compositor is an X11 client
++      of Xwayland. This circular dependency requires special care from the
++      Wayland compositor.
++    </para>
++  </section>
++  <section id="sect-X11-Application-Support-two-modes">
++    <title>Two Modes for Foreign Windows</title>
++    <para>
++      In general, windows from a foreign window system can be presented in one
++      of two ways: rootless and rootful (not rootless).
++    </para>
++    <para>
++      In rootful mode, the foreign window system as a whole is represented as a
++      window (or more) of its own. You have a native window, inside which all
++      the foreign windows are. The advantage of this approach in Xwayland's
++      case is that you can run your favourite X11 window manager to manage your
++      X11 applications. The disadvantage is that the foreign windows do not
++      integrate with the native desktop. Therefore this mode is not usually
++      used.
++    </para>
++    <para>
++      In rootless mode, each foreign window is a first-class resident among the
++      native windows. Foreign windows are not confined inside a native window
++      but act as if they were native windows. The advantage is that one can
++      freely stack and mix native and foreign windows, which is not possible in
++      rootful mode. The disadvantage is that this mode is harder to implement
++      and fundamental differences in window systems may prevent some things
++      from working. With rootless Xwayland, the Wayland compositor must take
++      the role as the X11 window manager, and one cannot use any other X11
++      window manager in its place.
++    </para>
++    <para>
++      This chapter concentrates on the rootless mode, and ignores the rootful
++      mode.
++    </para>
++  </section>
++  <section id="sect-X11-Application-Support-architecture">
++    <title>Architecture</title>
++    <para>
++      A Wayland compositor usually takes care of launching Xwayland.
++      Xwayland works in cooperation with a Wayland compositor as follows:
++    </para>
++    <figure>
++      <title>Xwayland architecture diagram</title>
++      <mediaobjectco>
++      <imageobjectco>
++        <imageobject>
++          <imagedata fileref="images/xwayland-architecture.png" format="PNG" />
++        </imageobject>
++      </imageobjectco>
++      </mediaobjectco>
++    </figure>
++    <para>
++      An X11 application connects to Xwayland just like it would connect to any
++      X server. Xwayland processes all the X11 requests. On the other end,
++      Xwayland is a Wayland client that connects to the Wayland compositor.
++    </para>
++    <para>
++      The X11 window manager (XWM) is an integral part of the Wayland
++      compositor. XWM uses the usual X11 window management protocol to manage
++      all X11 windows in Xwayland. Most importantly, XWM acts as a bridge
++      between Xwayland window state and the Wayland compositor's window manager
++      (WWM). This way WWM can manage all windows, both native Wayland and X11
++      (Xwayland) windows. This is very important for a coherent user
++      experience.
++    </para>
++    <para>
++      Since Xwayland uses Wayland for input and output, it does not have any
++      use for the device drivers that Xorg uses. None of the xf86-video-* or
++      xf86-input-* modules are used. There also is no configuration file for
++      the Xwayland server. For optional hardware accelerated rendering,
++      Xwayland uses GLAMOR.
++    </para>
++    <para>
++      A Wayland compositor usually spawns only one Xwayland instance. This is
++      because many X11 applications assume they can communicate with other X11
++      applications through the X server, and this requires a shared X server
++      instance. This also means that Xwayland does not protect nor isolate X11
++      clients from each other, unless the Wayland compositor specifically
++      chooses to break the X11 client intercommunications by spawning
++      application specific Xwayland instances. X11 clients are naturally
++      isolated from Wayland clients.
++    </para>
++    <para>
++      Xwayland compatibility compared to a native X server will probably never
++      reach 100%. Desktop environment (DE) components, specifically X11 window
++      managers, are practically never supported. An X11 window manager would
++      not know about native Wayland windows, so it could manage only X11
++      windows. On the other hand, there must be an XWM that reserves the
++      exclusive window manager role so that the Wayland compositor could show
++      the X11 windows appropriately. For other DE components, like pagers and
++      panels, adding the necessary interfaces to support them in WWM through XWM
++      is often considered not worthwhile.
++    </para>
++  </section>
++  <section id="sect-X11-Application-Support-xwm">
++    <title>X Window Manager (XWM)</title>
++    <para>
++      From the X11 point of view, the X window manager (XWM) living inside a
++      Wayland compositor is just like any other window manager. The difference
++      is mostly in which process it resides in, and the few extra conventions
++      in the X11 protocol to support Wayland window management (WWM)
++      specifically.
++    </para>
++    <para>
++      There are two separate asynchronous communication channels between
++      Xwayland and a Wayland compositor: one uses the Wayland protocol, and the
++      other one, solely for XWM, uses X11 protocol. This setting demands great
++      care from the XWM implementation to avoid (random) deadlocks with
++      Xwayland. It is often nearly impossible to prove that synchronous or
++      blocking X11 calls from XWM cannot cause a deadlock, and therefore it is
++      strongly recommended to make all X11 communications asynchronous. All
++      Wayland communications are already asynchronous by design.
++    </para>
++    <section id="sect-X11-Application-Support-xwm-window-identification">
++      <title>Window identification</title>
++      <para>
++      In Xwayland, an X11 window may have a corresponding wl_surface object
++      in Wayland. The wl_surface object is used for input and output: it is
++      referenced by input events and used to provide the X11 window content
++      to the Wayland compositor. The X11 window and the wl_surface live in
++      different protocol streams, and they need to be matched for XWM to do
++      its job.
++      </para>
++      <para>
++      When Xwayland creates a wl_surface on Wayland, it will also send an X11
++      ClientMessage of type atom "WL_SURFACE_ID" to the X11 window carrying
++      the wl_surface Wayland object ID as the first 32-bit data element. This
++      is how XWM can associate a wl_surface with an X11 window. Note that
++      the request to create a wl_surface and the ID message may arrive in any
++      order in the Wayland compositor.
++      </para>
++    </section>
++  </section>
++</chapter>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d86cba937909435f5cf731e075fef4994cf0dae8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,14 @@@
++/*headings*/
++h1, h2, h3, h4, h5, h6,
++div.producttitle,
++div.subtitle,
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib,
++.title,
++.titlepage .edition,
++.titlepage .releaseinfo {
++      color: #336699;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a05648ef59481afe827e9c1c6fbf95567dc45c35
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1769 @@@
++* {
++      widows: 4 !important;
++      orphans: 4 !important;
++}
++
++body, h1, h2, h3, h4, h5, h6, pre, li, div {
++      line-height: 1.29em;
++}
++
++body {
++      background-color: white;
++      margin:0 auto;
++      font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif;
++      font-size: 14px;
++      max-width: 770px;
++      color: black;
++}
++
++body.toc_embeded {
++      /*for web hosting system only*/
++      margin-left: 300px;
++}
++
++object.toc, iframe.toc {
++      /*for web hosting system only*/
++      border-style: none;
++      position: fixed;
++      width: 290px;
++      height: 99.99%;
++      top: 0;
++      left: 0;
++      z-index: 100;
++      border-style: none;
++      border-right:1px solid #999;
++}
++
++/* Hide web menu */
++
++body.notoc {
++      margin-left: 3em;
++}
++
++iframe.notoc {
++      border-style:none;
++      border: none;
++      padding: 0px;
++      position:fixed;
++      width: 21px;
++      height: 29px;
++      top: 0px;
++      left:0;
++      overflow: hidden;
++      margin: 0px;
++      margin-left: -3px;
++}
++/* End hide web menu */
++
++/* desktop styles */
++body.desktop {
++      margin-left: 26em;
++}
++
++body.desktop .book > .toc {
++      display:block;
++      width:24em;
++      height:99.99%;
++      position:fixed;
++      overflow:auto;
++      top:0px;
++      left:0px;
++/*    padding-left:1em; */
++      background-color:#EEEEEE;
++      font-size: 12px;
++}
++
++body.pdf {
++      max-width: 100%;
++}
++
++.toc {
++      line-height:1.35em;
++}
++
++.toc .glossary,
++.toc .chapter, .toc .appendix {
++      margin-top:1em;
++}
++
++.toc .part {
++      margin-top:1em;
++      display:block;
++}
++
++span.glossary,
++span.appendix {
++      display:block;
++      margin-top:0.5em;
++}
++
++div {
++      padding-top:0px;
++}
++
++div.section {
++      page-break-inside: avoid;
++}
++
++p, div.para {
++      padding-top: 0px;
++      margin-top: 1em;
++      padding-bottom: 0px;
++      margin-bottom: 1em;
++}
++
++div.formalpara {
++      padding-top: 0px;
++      margin-top: 1em;
++      padding-bottom: 0px;
++      margin-bottom: 1em;
++}
++
++.varlistentry div.para {
++      page-break-before: avoid;
++
++}
++
++/*Links*/
++a {
++      outline: none;
++}
++
++a:link {
++      text-decoration: none;
++      border-bottom: 1px dotted ;
++      color:#3366cc;
++}
++
++body.pdf a:link {
++      word-wrap: break-word;
++}
++
++a:visited {
++      text-decoration:none;
++      border-bottom: 1px dotted ;
++      color:#003366;
++}
++
++div.longdesc-link {
++      float:right;
++      color:#999;
++}
++
++.toc a, .qandaset a {
++      font-weight:normal;
++      border:none;
++}
++
++.toc a:hover, .qandaset a:hover
++{
++      border-bottom: 1px dotted;
++}
++
++/*headings*/
++h1, h2, h3, h4, h5, h6 {
++      color: #336699;
++      margin-top: 0px;
++      margin-bottom: 0px;
++      background-color: transparent;
++      margin-bottom: 0px;
++      margin-top: 20px;
++      page-break-inside: avoid;
++      page-break-after: avoid;
++      word-wrap: break-word;
++}
++
++h1 {
++      font-size: 22px;
++}
++
++.titlepage h1.title {
++      text-align:left;
++}
++
++.book > .titlepage h1.title {
++      text-align: center;
++}
++
++.article > .titlepage h1.title,
++.article > .titlepage h2.title {
++      text-align: center;
++}
++
++.set .titlepage > div > div > h1.title {
++      text-align: center;
++}
++
++.part > .titlepage h1.title {
++      text-align: center;
++      font-size: 24px;
++}
++
++div.producttitle {
++      margin-top: 0px;
++      margin-bottom: 20px;
++      font-size: 48px;
++      font-weight: bold;
++/*    background: #003d6e url(../images/h1-bg.png) top left repeat-x; */
++      color:  #336699;
++      text-align: center;
++      padding-top: 12px;
++}
++
++.titlepage .corpauthor {
++      margin-top: 1em;
++      text-align: center;
++}
++
++.section h1.title {
++      font-size: 18px;
++      padding: 0px;
++      color: #336699;
++      text-align: left;
++      background: white;
++}
++
++h2 {
++      font-size: 20px;
++      margin-top: 30px;
++}
++
++
++.book div.subtitle, .book h2.subtitle, .book h3.subtitle {
++      margin-top: 1em;
++      margin-bottom: 1em;
++      font-size: 18px;
++      text-align: center;
++}
++
++div.subtitle {
++      color:  #336699;
++      font-weight: bold;
++}
++
++h1.legalnotice {
++      font-size: 24px;
++}
++
++.preface > div > div > div > h2.title,
++.preface > div > div > div > h1.title {
++      margin-top: 1em;
++      font-size: 24px;
++}
++
++.appendix h2 {
++      font-size: 24px;
++}
++
++
++
++h3 {
++      font-size: 14px;
++      padding-top:0px;
++      padding-bottom: 0px;
++      margin-bottom: 0px;
++}
++h4 {
++      font-size: 14px;
++      padding-top:0px;
++      padding-bottom:0px;
++}
++
++h5 {
++      font-size: 14px;
++}
++
++h6 {
++      font-size: 14px;
++      margin-bottom: 0px;
++}
++
++.abstract h6 {
++      margin-top:1em;
++      margin-bottom:.5em;
++      font-size: 24px;
++}
++
++.index > div > div > div > h2.title {
++      font-size: 24px;
++}
++
++.chapter > div > div > div > h2.title {
++      font-size: 24px;
++}
++
++.section > div > div > div > h2.title {
++      font-size: 21px;
++      page-break-inside: avoid;
++      page-break-before: avoid;
++      page-break-after: avoid;
++}
++
++.section > div > div > div > h3.title {
++      font-size: 17px;
++}
++
++/*element rules*/
++hr {
++      border-collapse: collapse;
++      border-style:none;
++      border-top: 1px dotted #ccc;
++      width:100%;
++}
++
++/* web site rules */
++ul.languages, .languages li {
++      display:inline;
++      padding:0px;
++}
++
++.languages li a {
++      padding:0px .5em;
++      text-decoration: none;
++}
++
++.languages li p, .languages li div.para {
++      display:inline;
++}
++
++.languages li a:link, .languages li a:visited {
++      color:#444;
++}
++
++.languages li a:hover, .languages li a:focus, .languages li a:active {
++      color:black;
++}
++
++ul.languages {
++      display:block;
++      background-color:#eee;
++      padding:.5em;
++}
++
++/*supporting stylesheets*/
++
++/*unique to the webpage only*/
++.books {
++      position:relative;
++}
++
++.versions li {
++      width:100%;
++      clear:both;
++      display:block;
++}
++
++a.version {
++      font-size: 20px;
++      text-decoration:none;
++      width:100%;
++      display:block;
++      padding:1em 0px .2em 0px;
++      clear:both;
++}
++
++a.version:before {
++      content:"Version";
++      font-size: smaller;
++}
++
++a.version:visited, a.version:link {
++      color:#666;
++}
++
++a.version:focus, a.version:hover {
++      color:black;
++}
++
++.books {
++      display:block;
++      position:relative;
++      clear:both;
++      width:100%;
++}
++
++.books li {
++      display:block;
++      width:200px;
++      float:left;
++      position:relative;
++      clear: none ;
++}
++
++.books .html {
++      width:170px;
++      display:block;
++}
++
++.books .pdf {
++      position:absolute;
++      left:170px;
++      top:0px;
++      font-size: smaller;
++}
++
++.books .pdf:link, .books .pdf:visited {
++      color:#555;
++}
++
++.books .pdf:hover, .books .pdf:focus {
++      color:#000;
++}
++
++.books li a {
++      text-decoration:none;
++}
++
++.books li a:hover {
++      color:black;
++}
++
++/*products*/
++.products li {
++      display: block;
++      width:300px;
++      float:left;
++}
++
++.products li a {
++      width:300px;
++      padding:.5em 0px;
++}
++
++.products ul {
++      clear:both;
++}
++
++/*revision history*/
++.revhistory {
++      display:block;
++}
++
++.revhistory table {
++      background-color:transparent;
++      border-color:#fff;
++      padding:0px;
++      margin: 0;
++      border-collapse:collapse;
++      border-style:none;
++}
++
++.revhistory td {
++      text-align :left;
++      padding:0px;
++      border: none;
++      border-top: 1px solid #fff;
++      font-weight: bold;
++}
++
++.revhistory .simplelist td {
++      font-weight: normal;
++}
++
++.revhistory .simplelist {
++      margin-bottom: 1.5em;
++      margin-left: 1em;
++}
++
++.revhistory table th {
++      display: none;
++}
++
++
++/*credits*/
++.authorgroup div {
++      clear:both;
++      text-align: center;
++}
++
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib {
++      margin: 0px;
++      padding: 0px;
++      margin-top: 12px;
++      font-size: 14px;
++      font-weight: bold;
++      color: #336699;
++}
++
++div.editedby {
++      margin-top: 15px;
++      margin-bottom: -0.8em;
++}
++
++div.authorgroup .author,
++div.authorgroup.editor,
++div.authorgroup.translator,
++div.authorgroup.othercredit,
++div.authorgroup.contrib {
++      display: block;
++      font-size: 14px;
++      page-break-inside: avoid;
++}
++
++.revhistory .author {
++      display: inline;
++}
++
++.othercredit h3 {
++      padding-top: 1em;
++}
++
++
++.othercredit {
++      margin:0px;
++      padding:0px;
++}
++
++.releaseinfo {
++      clear: both;
++}
++
++.copyright {
++      margin-top: 1em;
++}
++
++/* qanda sets */
++.answer {
++      margin-bottom:1em;
++      border-bottom:1px dotted #ccc;
++}
++
++.qandaset .toc {
++      border-bottom:1px dotted #ccc;
++}
++
++.question {
++      font-weight:bold;
++}
++
++.answer .data, .question .data {
++      padding-left: 2.6em;
++}
++
++.answer .label, .question .label {
++      float:left;
++      font-weight:bold;
++}
++
++/* inline syntax highlighting */
++.perl_Alert {
++      color: #0000ff;
++}
++
++.perl_BaseN {
++      color: #007f00;
++}
++
++.perl_BString {
++      color: #5C3566;
++}
++
++.perl_Char {
++      color: #ff00ff;
++}
++
++.perl_Comment {
++      color: #888888;
++}
++
++
++.perl_DataType {
++      color: #0000ff;
++}
++
++
++.perl_DecVal {
++      color: #00007f;
++}
++
++
++.perl_Error {
++      color: #ff0000;
++}
++
++
++.perl_Float {
++      color: #00007f;
++}
++
++
++.perl_Function {
++      color: #007f00;
++}
++
++
++.perl_IString {
++      color: #5C3566;
++}
++
++
++.perl_Keyword {
++      color: #002F5D;
++}
++
++
++.perl_Operator {
++      color: #ffa500;
++}
++
++
++.perl_Others {
++      color: #b03060;
++}
++
++
++.perl_RegionMarker {
++      color: #96b9ff;
++}
++
++
++.perl_Reserved {
++      color: #9b30ff;
++}
++
++
++.perl_String {
++      color: #5C3566;
++}
++
++
++.perl_Variable {
++      color: #0000ff;
++}
++
++
++.perl_Warning {
++      color: #0000ff;
++}
++
++/*Lists*/
++ul {
++    list-style-image: url("../images/dot.png");
++    list-style-type: circle;
++    padding-left: 1.6em;
++}
++
++ul ul {
++    list-style-image: url("../images/dot2.png");
++    list-style-type: circle;
++}
++
++ol.1 {
++      list-style-type: decimal;
++}
++
++ol.a,
++ol ol {
++      list-style-type: lower-alpha;
++}
++
++ol.i {
++      list-style-type: lower-roman;
++}
++ol.A {
++      list-style-type: upper-alpha;
++}
++
++ol.I {
++      list-style-type: upper-roman;
++}
++
++dt {
++      font-weight:bold;
++      margin-bottom:0px;
++      padding-bottom:0px;
++}
++
++dd {
++      margin:0px;
++      margin-left:2em;
++      padding-top:0px;
++}
++
++li {
++      padding-top: 0px;
++      margin-top: 0px;
++      padding-bottom: 0px;
++/*    margin-bottom: 16px; */
++}
++
++/*images*/
++img {
++      display:block;
++      margin: 2em 0;
++      max-width: 100%;
++}
++
++.inlinemediaobject,
++.inlinemediaobject img,
++.inlinemediaobject object {
++      display:inline;
++      margin:0px;
++      overflow: hidden;
++}
++
++.figure {
++    margin-top: 1em;
++    width: 100%;
++}
++
++.figure img,
++.mediaobject img {
++      display:block;
++      margin: 0em;
++      page-break-inside: avoid;
++}
++
++.figure .title {
++      margin-bottom:2em;
++      padding:0px;
++}
++
++/*document modes*/
++.confidential {
++      background-color:#900;
++      color:White;
++      padding:.5em .5em;
++      text-transform:uppercase;
++      text-align:center;
++}
++
++.longdesc-link {
++      display:none;
++}
++
++.longdesc {
++      display:none;
++}
++
++.prompt {
++      padding:0px .3em;
++}
++
++/*user interface styles*/
++.screen .replaceable {
++}
++
++.guibutton, .guilabel {
++      font-family: "liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++      font-weight: bold;
++}
++
++.example {
++      background-color: #ffffff;
++      border-left: 3px solid #aaaaaa;
++      padding-top: 1px;
++      padding-bottom: 0.1em;
++      padding-left: 1em;
++}
++
++.equation {
++      border-left: 3px solid #aaaaaa;
++      background-color: #ffffff;
++      padding-top: 1px;
++      padding-bottom: 0.1em;
++      padding-left: 1em;
++}
++
++.equation-contents {
++      margin-left: 4em;
++}
++
++div.title {
++      margin-bottom: 1em;
++      font-weight: 14px;
++      font-weight: bold;
++      color: #336699;
++      page-break-inside: avoid;
++      page-break-after: avoid;
++      word-wrap: break-word;
++}
++
++.example-contents {
++      background-color: #ffffff;
++}
++
++.example-contents .para {
++/*     padding: 10px;*/
++}
++
++/*terminal/console text*/
++.computeroutput,
++.option {
++      font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++      font-weight:bold;
++}
++
++.replaceable {
++      font-style: italic;
++}
++
++.command, .filename, .keycap, .classname, .literal {
++      font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++      font-weight:bold;
++}
++
++/* no bold in toc */
++.toc * {
++      font-weight: inherit;
++}
++
++.toc H1 {
++      font-weight: bold;
++}
++
++
++div.programlisting {
++      white-space: pre-wrap; /* css-3 */
++      white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++      white-space: -pre-wrap; /* Opera 4-6 */
++      white-space: -o-pre-wrap; /* Opera 7 */
++      word-wrap: break-word; /* Internet Explorer 5.5+ */
++}
++
++pre {
++      font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++      display:block;
++      background-color: #f5f5f5;
++      color: #000000;
++/*    border: 1px solid #aaaaaa; */
++      margin-bottom: 1em;
++      padding:.5em 1em;
++      white-space: pre-wrap; /* css-3 */
++      white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++      white-space: -pre-wrap; /* Opera 4-6 */
++      white-space: -o-pre-wrap; /* Opera 7 */
++      word-wrap: break-word; /* Internet Explorer 5.5+ */
++      font-size: 0.9em;
++      border-style:none;
++      box-shadow: 0 2px 5px #AAAAAA inset;
++      -moz-box-shadow:  0 2px 5px #AAAAAA inset;
++      -webkit-box-shadow: 0 2px 5px #AAAAAA inset;
++      -o-box-shadow: 0 2px 5px #AAAAAA inset;
++}
++
++body.pdf pre {
++      border: 1px solid #AAAAAA;
++      box-shadow: none;
++      -moz-box-shadow: none;
++      -webkit-box-shadow: none;
++      -o-box-shadow: none;
++}
++
++
++pre .replaceable,
++pre .keycap {
++}
++
++code {
++      font-family:"liberation mono", "bitstream vera mono", "dejavu mono", monospace;
++      white-space: pre-wrap;
++      word-wrap: break-word;
++      font-weight:bold;
++}
++
++.parameter code {
++      display: inline;
++      white-space: pre-wrap; /* css-3 */
++      white-space: -moz-pre-wrap !important; /* Mozilla, since 1999 */
++      white-space: -pre-wrap; /* Opera 4-6 */
++      white-space: -o-pre-wrap; /* Opera 7 */
++      word-wrap: break-word; /* Internet Explorer 5.5+ */
++}
++
++code.email {
++      font-weight: normal;
++      font-family: "liberation sans", "Myriad ", "Bitstream Vera Sans", "Lucida Grande", "Luxi Sans", "Trebuchet MS", helvetica, verdana, arial, sans-serif;
++
++}
++
++/*Notifications*/
++div.warning:before {
++      content:url(../images/warning.png);
++      padding-left: 5px;
++}
++
++div.note:before {
++      content:url(../images/note.png);
++      padding-left: 5px;
++}
++
++div.important:before {
++      content:url(../images/important.png);
++      padding-left: 5px;
++}
++
++div.warning, div.note, div.important {
++      color: black;
++      margin: 0px;
++      padding: 0px;
++      background: none;
++      background-color: white;
++      margin-bottom: 1em;
++      border-bottom: 1px solid #aaaaaa;
++      page-break-inside: avoid;
++}
++
++div.admonition_header p {
++      margin: 0px;
++      padding: 0px;
++      color: #eeeeec;
++      padding-top: 0px;
++      padding-bottom: 0px;
++      height: 1.4em;
++      line-height: 1.4em;
++      font-size: 17px;
++      display:inline;
++}
++
++div.admonition_header {
++      background-origin:content-box;
++      clear: both;
++      margin: 0px;
++      padding: 0px;
++      margin-top: -40px;
++      padding-left: 58px;
++      line-height: 1.0px;
++      font-size: 1.0px;
++}
++
++div.warning div.admonition_header {
++      background: url(../images/red.png) top left repeat-x;
++      background-color: #590000;
++      background: -webkit-linear-gradient(#a40000,#590000);
++      background: linear-gradient(#a40000,#590000);
++}
++
++div.note div.admonition_header {
++      background: url(../images/green.png) top right repeat-x;
++      background-color: #597800;
++      background: -webkit-linear-gradient(#769f00,#597800);
++      background: linear-gradient(#769f00,#597800);
++}
++
++div.important div.admonition_header {
++      background: url(../images/yellow.png) top right repeat-x;
++      background-color: #a6710f;
++      background: -webkit-linear-gradient(#d08e13,#a6710f);
++      background: linear-gradient(#d08e13,#a6710f);
++}
++
++div.warning p:first-child,
++div.warning div.para:first-child,
++div.note p:first-child,
++div.note div.para:first-child,
++div.important p:first-child,
++div.important div.para:first-child {
++      padding: 0px;
++      margin: 0px;
++}
++
++div.admonition {
++      border: none;
++      border-left: 1px solid #aaaaaa;
++      border-right: 1px solid #aaaaaa;
++      padding:0px;
++      margin:0px;
++      padding-top: 1.5em;
++      padding-bottom: 1em;
++      padding-left: 2em;
++      padding-right: 1em;
++      background-color: #eeeeec;
++      -moz-border-radius: 0px;
++      -webkit-border-radius: 0px;
++      border-radius: 0px;
++}
++
++/*Page Title*/
++#title  {
++      display:block;
++      height:45px;
++      padding-bottom:1em;
++      margin:0px;
++}
++
++#title a.left{
++      display:inline;
++      border:none;
++}
++
++#title a.left img{
++      border:none;
++      float:left;
++      margin:0px;
++      margin-top:.7em;
++}
++
++#title a.right {
++      padding-bottom:1em;
++}
++
++#title a.right img {
++      border:none;
++      float:right;
++      margin:0px;
++      margin-top:.7em;
++}
++
++/*Table*/
++div.table {
++/*    page-break-inside: avoid; */
++}
++
++table {
++      border: 1px solid #444;
++      width:100%;
++      border-collapse:collapse;
++      table-layout: fixed;
++      word-wrap: break-word;
++}
++
++table.blockquote,
++table.simplelist,
++.calloutlist table {
++      border-style: none;
++}
++
++table th {
++      text-align:left;
++      background-color:#6699cc;
++      padding:.3em .5em;
++      color:white;
++}
++
++table td {
++      padding:.15em .5em;
++}
++
++table tr.even td {
++      background-color:#f5f5f5;
++}
++
++tr:nth-child(even) {
++      background-color: #eeeeee;
++
++}
++
++
++table th p:first-child, table td p:first-child, table  li p:first-child,
++table th div.para:first-child, table td div.para:first-child, table  li div.para:first-child {
++      margin-top:0px;
++      padding-top:0px;
++      display:inline;
++}
++
++th, td {
++      border-style:none;
++      vertical-align: top;
++/*    border: 1px solid #000; */
++}
++
++.blockquote td,
++.simplelist th,
++.simplelist td {
++      border: none;
++}
++
++table table td {
++      border-bottom:1px dotted #aaa;
++      background-color:white;
++      padding:.6em 0px;
++}
++
++table table {
++      border:1px solid white;
++}
++
++td.remarkval {
++      color:#444;
++}
++
++td.fieldval {
++      font-weight:bold;
++}
++
++.lbname, .lbtype, .lbdescr, .lbdriver, .lbhost {
++      color:white;
++      font-weight:bold;
++      background-color:#999;
++      width:120px;
++}
++
++td.remarkval {
++      width:230px;
++}
++
++td.tname {
++      font-weight:bold;
++}
++
++th.dbfield {
++      width:120px;
++}
++
++th.dbtype {
++      width:70px;
++}
++
++th.dbdefault {
++      width:70px;
++}
++
++th.dbnul {
++      width:70px;
++}
++
++th.dbkey {
++      width:70px;
++}
++
++span.book {
++      margin-top:4em;
++      display:block;
++      font-size: 11pt;
++}
++
++span.book a{
++      font-weight:bold;
++}
++span.chapter {
++      display:block;
++}
++
++table.simplelist td, .calloutlist table td {
++      border-style: none;
++}
++
++
++table.lt-4-cols.lt-7-rows td {
++      border: none;
++}
++/*to simplify layout*/
++
++
++table.lt-4-cols.gt-14-rows tr:nth-child(odd) {
++      background-color: #fafafa;
++}
++/* to keep simple but stripe rows */
++
++
++.gt-8-cols td {
++      border-left: 1px solid #ccc;
++}
++
++.gt-8-cols td:first-child {
++      border-left: 0;
++}
++/* to apply vertical lines to differentiate columns*/
++
++/*Breadcrumbs*/
++#breadcrumbs ul li.first:before {
++      content:" ";
++}
++
++#breadcrumbs {
++      color:#900;
++      padding:3px;
++      margin-bottom:25px;
++}
++
++#breadcrumbs ul {
++      margin-left:0;
++      padding-left:0;
++      display:inline;
++      border:none;
++}
++
++#breadcrumbs ul li {
++      margin-left:0;
++      padding-left:2px;
++      border:none;
++      list-style:none;
++      display:inline;
++}
++
++#breadcrumbs ul li:before {
++      content:"\0020 \0020 \0020 \00BB \0020";
++      color:#333;
++}
++
++dl {
++      margin-top: 0px;
++      margin-left: 28px;
++}
++
++.toc dl {
++      margin-left: 10px;
++}
++
++/*index*/
++.glossary h3,
++.index h3 {
++      font-size: 20px;
++      color:#aaa;
++      margin:0px;
++}
++
++.indexdiv {
++      margin-bottom:1em;
++}
++
++.glossary dt,
++.index dt {
++      color:#444;
++      padding-top:.5em;
++}
++
++.glossary dl dl dt,
++.index dl dl dt {
++      color:#777;
++      font-weight:normal;
++      padding-top:0px;
++}
++
++.index dl dl dt:before {
++      content:"- ";
++      color:#ccc;
++}
++
++/*changes*/
++.footnote {
++      font-size: 10px;
++      margin: 0px;
++      color: #222;
++}
++
++.footnotes {
++      margin-bottom: 60px;
++}
++
++table .footnote {
++}
++
++sup {
++      margin:0px;
++      padding:0px;
++      font-size: 10px;
++      padding-left:0px;
++}
++
++.footnote {
++      position:relative;
++}
++
++.footnote sup  {
++      color: black;
++      left: .4em;
++}
++
++.footnote a:link,
++.footnote a:visited {
++      text-decoration:none;
++      border: none;
++}
++
++.footnote .para sup  {
++/*    position:absolute; */
++      vertical-align:text-bottom;
++}
++
++a.footnote {
++      padding-right: 0.5em;
++      text-decoration:none;
++      border: none;
++}
++
++.footnote sup a:link,
++.footnote sup a:visited {
++      color:#92917d;
++      text-decoration:none;
++}
++
++.footnote:hover sup a {
++      text-decoration:none;
++}
++
++.footnote p,.footnote div.para {
++      padding-left:1em;
++}
++
++.footnote a:link,
++.footnote a:visited before{
++      color:#00537c;
++}
++
++.footnote a:hover {
++}
++
++/**/
++.pdf-break {
++      page-break-before: always;
++}
++
++div.legalnotice {
++      page-break-before: always;
++}
++
++div.abstract {
++      page-break-before: always;
++/*    page-break-after: always;*/
++}
++
++div.chapter {
++      page-break-before: always;
++}
++
++
++div.titlepage, div.titlepage > div, div.titlepage > div > div {
++      page-break-inside: avoid;
++      page-break-after: avoid;
++}
++
++div.preface, div.part {
++      page-break-before: always;
++}
++
++div.appendix {
++      page-break-before: always;
++}
++
++div.section {
++      page-break-inside: auto;
++      page-break-before: auto;
++      page-break-after: auto;
++}
++
++
++dt.varlistentry {
++      page-break-inside: avoid;
++      page-break-after: avoid;
++}
++
++dd {
++      page-break-before: avoid;
++}
++
++div.note .replaceable,
++div.important .replaceable,
++div.warning .replaceable,
++div.note .keycap,
++div.important .keycap,
++div.warning .keycap
++{
++}
++
++ul li p:last-child, ul li para:last-child {
++      margin-bottom:0px;
++      padding-bottom:0px;
++}
++
++/*document navigation*/
++.docnav a, .docnav strong {
++      border:none;
++      text-decoration:none;
++      font-weight:normal;
++}
++
++.docnav {
++      list-style:none;
++      margin:0px;
++      padding:0px;
++      position:relative;
++      width:100%;
++      padding-bottom:2em;
++      padding-top:1em;
++        height:2.5em;
++        line-height:2.5em;
++/*
++      border-top:1px dotted #ccc;
++        background-color: rgba(240, 240, 240, 0.9);
++-webkitbox-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++  -moz-box-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++       box-shadow: 0px .15em .5em rgba(0,0,0,0.2);
++*/
++}
++
++.docnav li {
++      list-style:none;
++      margin:0px;
++      padding:0px;
++      display:inline;
++      font-size: 14px;
++}
++
++.docnav li:before {
++      content:" ";
++}
++
++.docnav li.previous, .docnav li.next {
++      position:absolute;
++      top:1.5em;
++}
++
++.docnav li.up, .docnav li.home {
++      margin:0px 1.5em;
++}
++
++.docnav.top li.home {
++      color: #336699;
++      font-size: 22pt;
++      font-weight: bold;
++}
++
++
++.docnav li.previous {
++      left:0px;
++      text-align:left;
++}
++
++.docnav li.next {
++      right:0px;
++      text-align:right;
++}
++
++.docnav li.previous strong, .docnav li.next strong {
++      height: 17px;
++      display: block;
++}
++
++.docnav {
++      margin:0 auto;
++      text-align:center;
++}
++
++.docnav li.next a strong {
++      background:  url(../images/stock-go-forward.png) right 120% no-repeat;
++      padding-top:3px;
++      padding-bottom:4px;
++      padding-right:28px;
++}
++
++.docnav li.previous a strong {
++      background: url(../images/stock-go-back.png) left 120% no-repeat;
++      padding-top:3px;
++      padding-bottom:4px;
++      padding-left:28px;
++      padding-right:0.5em;
++}
++
++.docnav li.home a strong {
++      background: url(../images/stock-home.png) top left no-repeat;
++      padding:5px;
++      padding-left:28px;
++}
++
++.docnav li.up a strong {
++      background: url(../images/stock-go-up.png) top left no-repeat;
++      padding:5px;
++      padding-left:28px;
++}
++
++.docnav a:link, .docnav a:visited {
++      color:#666;
++}
++
++.docnav a:hover, .docnav a:focus, .docnav a:active {
++      color:black;
++}
++
++.docnav a {
++      max-width: 10px;
++      overflow:hidden;
++}
++
++.docnav a:link strong {
++      text-decoration:none;
++}
++
++.docnav {
++      margin:0 auto;
++      text-align:center;
++}
++
++ul.docnav {
++      margin-bottom: 1em;
++}
++/* Reports */
++.reports ul {
++      list-style:none;
++      margin:0px;
++      padding:0px;
++}
++
++.reports li{
++      margin:0px;
++      padding:0px;
++}
++
++.reports li.odd {
++      background-color: #eeeeee;
++      margin:0px;
++      padding:0px;
++}
++
++.reports dl {
++      display:inline;
++      margin:0px;
++      padding:0px;
++      float:right;
++      margin-right: 17em;
++      margin-top:-1.3em;
++}
++
++.reports dt {
++      display:inline;
++      margin:0px;
++      padding:0px;
++}
++
++.reports dd {
++      display:inline;
++      margin:0px;
++      padding:0px;
++      padding-right:.5em;
++}
++
++.reports h2, .reports h3{
++      display:inline;
++      padding-right:.5em;
++      font-size: 14px;
++      font-weight:normal;
++}
++
++.reports div.progress {
++      display:inline;
++      float:right;
++      width:16em;
++      background:#c00 url(../images/shine.png) top left repeat-x;
++      margin:0px;
++      margin-top:-1.3em;
++      padding:0px;
++      border:none;
++}
++
++/*uniform*/
++body.results, body.reports {
++      max-width:57em ;
++      padding:0px;
++}
++
++/*Progress Bar*/
++div.progress {
++      display:block;
++      float:left;
++      width:16em;
++      background:#c00 url(../images/shine.png) top left repeat-x;
++      height:1em;
++}
++
++div.progress span {
++      height:1em;
++      float:left;
++}
++
++div.progress span.translated {
++      background:#6c3 url(../images/shine.png) top left repeat-x;
++}
++
++div.progress span.fuzzy {
++      background:#ff9f00 url(../images/shine.png) top left repeat-x;
++}
++
++
++/*Results*/
++
++.results ul {
++      list-style:none;
++      margin:0px;
++      padding:0px;
++}
++
++.results li{
++      margin:0px;
++      padding:0px;
++}
++
++.results li.odd {
++      background-color: #eeeeee;
++      margin:0px;
++      padding:0px;
++}
++
++.results dl {
++      display:inline;
++      margin:0px;
++      padding:0px;
++      float:right;
++      margin-right: 17em;
++      margin-top:-1.3em;
++}
++
++.results dt {
++      display:inline;
++      margin:0px;
++      padding:0px;
++}
++
++.results dd {
++      display:inline;
++      margin:0px;
++      padding:0px;
++      padding-right:.5em;
++}
++
++.results h2, .results h3 {
++      display:inline;
++      padding-right:.5em;
++      font-size: 14px;
++      font-weight:normal;
++}
++
++.results div.progress {
++      display:inline;
++      float:right;
++      width:16em;
++      background:#c00 url(../images/shine.png) top left repeat-x;
++      margin:0px;
++      margin-top:-1.3em;
++      padding:0px;
++      border:none;
++}
++
++/* Dirty EVIL Mozilla hack for round corners */
++pre {
++      -moz-border-radius:11px;
++      -webkit-border-radius:11px;
++      border-radius: 11px;
++/*    page-break-inside: avoid; */
++}
++
++.example {
++      -moz-border-radius:0px;
++      -webkit-border-radius:0px;
++      border-radius: 0px;
++      page-break-inside: avoid;
++}
++
++/* move these invisible fields out of the flow */
++.example > a:first-child,
++.table > a:first-child {
++    float: left;
++}
++
++.package, .citetitle {
++      font-style: italic;
++}
++
++.titlepage .edition,
++.titlepage .releaseinfo {
++      color: #336699;
++      background-color: transparent;
++      margin-top: 1em;
++      margin-bottom: 1em;
++      font-size: 20px;
++      font-weight: bold;
++      text-align: center;
++}
++
++span.remark {
++      background-color: #ff00ff;
++}
++
++.draft {
++      background-image: url(../images/watermark-draft.png);
++      background-repeat: repeat-y;
++        background-position: center;
++}
++
++.foreignphrase {
++      font-style: inherit;
++}
++
++dt {
++      clear:both;
++      page-break-inside: avoid;
++      page-break-after: avoid;
++}
++
++dt img {
++      border-style: none;
++      max-width: 112px;
++}
++
++dt object {
++      max-width: 112px;
++}
++
++dt .inlinemediaobject, dt object {
++      display: inline;
++      float: left;
++      margin-bottom: 1em;
++      padding-right: 1em;
++      width: 112px;
++}
++
++dl:after {
++      display: block;
++      clear: both;
++      content: "";
++}
++
++.toc dd {
++      padding-bottom: 0px;
++      margin-bottom: 1em;
++      padding-left: 1.3em;
++      margin-left: 0px;
++}
++
++div.toc > dl > dt {
++      padding-bottom: 0px;
++      margin-bottom: 0px;
++      margin-top: 1em;
++}
++
++
++.strikethrough {
++      text-decoration: line-through;
++}
++
++.underline {
++      text-decoration: underline;
++}
++
++.calloutlist img, .callout {
++      padding: 0px;
++      margin: 0px;
++      width: 12pt;
++      display: inline;
++      vertical-align: middle;
++}
++
++li.step > a:first-child {
++      display: block;
++}
++
++.stepalternatives {
++      list-style-image: none;
++      list-style-type: upper-alpha;
++}
++.task {
++/*    page-break-inside: avoid; */
++}
++
++
++.added {
++      background-color: #99ff99;
++}
++
++.changed {
++      background-color: #ffff77;
++}
++
++.deleted {
++      background-color: #ff4455;
++      text-decoration: line-through;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bf38ebb59311a770914945ae9f98979a48506a7a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3 @@@
++@import url("common.css");
++@import url("overrides.css");
++@import url("lang.css");
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b0ffd43cb791141b05f6d51c5a92179f5f07c012
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,115 @@@
++/*headings*/
++h1, h2, h3, h4, h5, h6,
++div.producttitle,
++div.subtitle,
++div.author div.author,
++div.translator div.translator,
++div.othercredit div.othercredit,
++div.editor div.editor,
++div.contrib div.contrib,
++.title,
++.titlepage .edition {
++}
++
++div.para {
++      margin-top: 1em;
++}
++/* inline syntax highlighting */
++.perl_Alert {
++      color: #0000ff;
++}
++
++.perl_BaseN {
++      color: #007f00;
++}
++
++.perl_BString {
++      color: #5C3566;
++}
++
++.perl_Char {
++      color: #ff00ff;
++}
++
++.perl_Comment {
++      color: #888888;
++}
++
++
++.perl_DataType {
++      color: #0000ff;
++}
++
++
++.perl_DecVal {
++      color: #00007f;
++}
++
++
++.perl_Error {
++      color: #ff0000;
++}
++
++
++.perl_Float {
++      color: #00007f;
++}
++
++
++.perl_Function {
++      color: #007f00;
++}
++
++
++.perl_IString {
++      color: #5C3566;
++}
++
++
++.perl_Keyword {
++      color: #002F5D;
++}
++
++
++.perl_Operator {
++      color: #ffa500;
++}
++
++
++.perl_Others {
++      color: #b03060;
++}
++
++
++.perl_RegionMarker {
++      color: #96b9ff;
++}
++
++
++.perl_Reserved {
++      color: #9b30ff;
++}
++
++
++.perl_String {
++      color: #5C3566;
++}
++
++
++.perl_Variable {
++      color: #0000ff;
++}
++
++
++.perl_Warning {
++      color: #0000ff;
++}
++
++b, strong {
++      font-weight: bolder;
++}
++
++code.command {
++      font-family: monospace;
++      font-weight: bolder;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..54088f48d6d5010601dd88b34ce1e533f81cba95
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,15 @@@
++@import url("common.css");
++@import url("overrides.css");
++@import url("lang.css");
++
++#tocframe {
++      display: none;
++}
++
++body.toc_embeded {
++      margin-left: 30px;
++}
++
++.producttitle {
++      color: #336699;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b2f16d0f61d039f7e50c344cdcdd544210cc418c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,19 @@@
++<?xml version="1.0" encoding="UTF-8" standalone="no"?>
++<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0" width="32" height="32" id="svg3017">
++  <defs id="defs3019">
++    <linearGradient id="linearGradient2381">
++      <stop id="stop2383" style="stop-color:#ffffff;stop-opacity:1" offset="0"/>
++      <stop id="stop2385" style="stop-color:#ffffff;stop-opacity:0" offset="1"/>
++    </linearGradient>
++    <linearGradient x1="296.4996" y1="188.81061" x2="317.32471" y2="209.69398" id="linearGradient2371" xlink:href="#linearGradient2381" gradientUnits="userSpaceOnUse" gradientTransform="matrix(0.90776,0,0,0.90776,24.35648,49.24131)"/>
++  </defs>
++  <g transform="matrix(0.437808,-0.437808,0.437808,0.437808,-220.8237,43.55311)" id="g5089">
++    <path d="m 8.4382985,-6.28125 c -0.6073916,0 -4.3132985,5.94886271 -4.3132985,8.25 l 0,26.71875 c 0,0.846384 0.5818159,1.125 1.15625,1.125 l 25.5625,0 c 0.632342,0 1.125001,-0.492658 1.125,-1.125 l 0,-5.21875 0.28125,0 c 0.49684,0 0.906249,-0.409411 0.90625,-0.90625 l 0,-27.9375 c 0,-0.4968398 -0.40941,-0.90625 -0.90625,-0.90625 l -23.8117015,0 z" transform="translate(282.8327,227.1903)" id="path5091" style="fill:#5c5c4f;stroke:#000000;stroke-width:3.23021388;stroke-miterlimit:4;stroke-dasharray:none"/>
++    <rect width="27.85074" height="29.369793" rx="1.1414107" ry="1.1414107" x="286.96509" y="227.63805" id="rect5093" style="fill:#032c87"/>
++    <path d="m 288.43262,225.43675 25.2418,0 0,29.3698 -26.37615,0.0241 1.13435,-29.39394 z" id="rect5095" style="fill:#ffffff"/>
++    <path d="m 302.44536,251.73726 c 1.38691,7.85917 -0.69311,11.28365 -0.69311,11.28365 2.24384,-1.60762 3.96426,-3.47694 4.90522,-5.736 0.96708,2.19264 1.83294,4.42866 4.27443,5.98941 0,0 -1.59504,-7.2004 -1.71143,-11.53706 l -6.77511,0 z" id="path5097" style="fill:#a70000;fill-opacity:1;stroke-width:2"/>
++    <rect width="25.241802" height="29.736675" rx="0.89682275" ry="0.89682275" x="290.73544" y="220.92249" id="rect5099" style="fill:#809cc9"/>
++    <path d="m 576.47347,725.93939 6.37084,0.41502 0.4069,29.51809 c -1.89202,-1.31785 -6.85427,-3.7608 -8.26232,-1.68101 l 0,-26.76752 c 0,-0.82246 0.66212,-1.48458 1.48458,-1.48458 z" transform="matrix(0.499065,-0.866565,0,1,0,0)" id="rect5101" style="fill:#4573b3;fill-opacity:1"/>
++    <path d="m 293.2599,221.89363 20.73918,0 c 0.45101,0 0.8141,0.3631 0.8141,0.81411 0.21547,6.32836 -19.36824,21.7635 -22.36739,17.59717 l 0,-17.59717 c 0,-0.45101 0.3631,-0.81411 0.81411,-0.81411 z" id="path5103" style="opacity:0.65536726;fill:url(#linearGradient2371);fill-opacity:1"/>
++  </g>
++</svg>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c9937928ce9584a660ee10f7092eed2033f6eab8
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f24dc1837f2e190c9d38719420a844aeb5997efa
new file mode 100644 (file)
Binary files differ
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..52f3a681310606527954fb5e2271977ece8165ce
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,113 @@@
++ProtocolSpec_xml = custom_target(
++      'ProtocolSpec.xml',
++      command: [ xsltproc, '-o', '@OUTPUT@', files('../protocol-to-docbook.xsl'), '@INPUT@' ],
++      input: wayland_protocol_xml,
++      output: 'ProtocolSpec.xml'
++)
++
++ProtocolInterfaces_xml = custom_target(
++      'ProtocolInterfaces.xml',
++      command: [ xsltproc, '-o', '@OUTPUT@', files('../protocol-interfaces-to-docbook.xsl'), '@INPUT@' ],
++      input: wayland_protocol_xml,
++      output: 'ProtocolInterfaces.xml'
++)
++
++ClientAPI_combined = custom_target(
++      'ClientAPI-combined',
++      command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
++      input: [ doxygen_Client_combine_xslt, doxygen_Client_index_xml ],
++      output: 'ClientAPI-combined.xml'
++)
++
++to_publican_xsl = files('../doxygen-to-publican.xsl')
++
++ClientAPI_xml = custom_target(
++      'ClientAPI.xml',
++      command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Client', to_publican_xsl, '@INPUT@' ],
++      input: ClientAPI_combined,
++      output: 'ClientAPI.xml'
++)
++
++ServerAPI_combined = custom_target(
++      'ServerAPI-combined',
++      command: [ xsltproc, '-o', '@OUTPUT@', '@INPUT@' ],
++      input: [ doxygen_Server_combine_xslt, doxygen_Server_index_xml ],
++      output: 'ServerAPI-combined.xml'
++)
++
++ServerAPI_xml = custom_target(
++      'ServerAPI.xml',
++      command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'which', 'Server', to_publican_xsl, '@INPUT@' ],
++      input: ServerAPI_combined,
++      output: 'ServerAPI.xml'
++)
++
++
++publican_sources = [
++      'Wayland.ent',
++      # 'Wayland.xml', # handled specially
++      'Book_Info.xml',
++      'Author_Group.xml',
++      'Foreword.xml',
++      'Preface.xml',
++      'Revision_History.xml',
++      'Protocol.xml',
++      'Xwayland.xml',
++      'Compositors.xml',
++      'Client.xml',
++      'Server.xml'
++]
++
++publican_processed_main = configure_file(
++      input: 'Wayland.xml',
++      output: 'Wayland.xml',
++      copy: true
++)
++
++publican_copied_sources = []
++foreach src: publican_sources
++      publican_copied_sources += configure_file(
++              input: src,
++              output: src,
++              copy: true
++      )
++endforeach
++
++publican_processed_sources = [
++      'Architecture.xml',
++      'Introduction.xml'
++]
++
++publican_processed_targets = []
++foreach src: publican_processed_sources
++      publican_processed_targets += custom_target(
++              src,
++              command: [ xsltproc, '-o', '@OUTPUT@', '--stringparam', 'basedir', '.', merge_mapcoords_xsl, '@INPUT@' ],
++              input: src,
++              output: src
++      )
++endforeach
++
++publican_css_sources = files([
++      'css/brand.css',
++      'css/common.css',
++      'css/default.css',
++      'css/epub.css',
++      'css/print.css'
++])
++
++install_data(
++      publican_css_sources,
++      install_dir: join_paths(publican_install_prefix, publican_html_dir, 'css')
++)
++
++publican_img_sources = files([
++      'images/icon.svg',
++      'images/wayland.png',
++      'images/xwayland-architecture.png'
++])
++
++install_data(
++      publican_img_sources,
++      install_dir: join_paths(publican_install_prefix, publican_html_dir, 'images')
++)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b3cbdf310ff00a89610daed8ad7228b230bbad2e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,52 @@@
++wayland_egl = library(
++      'wayland-egl',
++      sources: [
++              'wayland-egl.c',
++              wayland_client_protocol_h
++      ],
++      include_directories: src_inc,
++      version: meson.project_version(),
++      install: true
++)
++
++executable('wayland-egl-abi-check', 'wayland-egl-abi-check.c')
++
++nm_path = find_program('nm').full_path()
++
++test(
++      'wayland-egl symbols check',
++      find_program('wayland-egl-symbols-check'),
++      env: [
++              'WAYLAND_EGL_LIB=@0@'.format(wayland_egl.full_path()),
++              'NM=@0@'.format(nm_path)
++      ]
++)
++
++install_headers([
++      'wayland-egl.h',
++      'wayland-egl-core.h',
++      'wayland-egl-backend.h'
++])
++
++pkgconfig.generate(
++      name: 'wayland-egl',
++      description: 'Frontend wayland-egl library',
++      version: '18.1.0',
++      requires: 'wayland-client',
++      libraries: wayland_egl
++)
++
++pkgconfig.generate(
++      name: 'wayland-egl-backend',
++      description: 'Backend wayland-egl interface',
++      version: '3'
++)
++
++wayland_egl_dep = declare_dependency(
++      link_with: wayland_egl,
++      include_directories: [ root_inc, include_directories('.') ],
++)
++
++if meson.version().version_compare('>= 0.54.0')
++      meson.override_dependency('wayland-egl', wayland_egl_dep)
++endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ea877d0e5428f451a7f9aa376c95b7d8c6decc74
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,235 @@@
++/*
++ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice shall be included in
++ * all copies or substantial portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
++ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ */
++
++#include <stddef.h> /* offsetof */
++#include <stdio.h>  /* printf */
++
++#include "wayland-egl-backend.h" /* Current struct wl_egl_window implementation */
++
++/*
++ * Following are previous implementations of wl_egl_window.
++ *
++ * DO NOT EVER CHANGE!
++ */
++
++/* From: 214fc6e850 - Benjamin Franzke : egl: Implement libwayland-egl */
++struct wl_egl_window_v0 {
++    struct wl_surface *surface;
++
++    int width;
++    int height;
++    int dx;
++    int dy;
++
++    int attached_width;
++    int attached_height;
++};
++
++/* From: ca3ed3e024 - Ander Conselvan de Oliveira : egl/wayland: Don't invalidate drawable on swap buffers */
++struct wl_egl_window_v1 {
++    struct wl_surface *surface;
++
++    int width;
++    int height;
++    int dx;
++    int dy;
++
++    int attached_width;
++    int attached_height;
++
++    void *private;
++    void (*resize_callback)(struct wl_egl_window *, void *);
++};
++
++/* From: 690ead4a13 - Stencel, Joanna : egl/wayland-egl: Fix for segfault in dri2_wl_destroy_surface. */
++#define WL_EGL_WINDOW_VERSION_v2 2
++struct wl_egl_window_v2 {
++    struct wl_surface *surface;
++
++    int width;
++    int height;
++    int dx;
++    int dy;
++
++    int attached_width;
++    int attached_height;
++
++    void *private;
++    void (*resize_callback)(struct wl_egl_window *, void *);
++    void (*destroy_window_callback)(void *);
++};
++
++/* From: 2d5d61bc49 - Miguel A. Vico : wayland-egl: Make wl_egl_window a versioned struct */
++#define WL_EGL_WINDOW_VERSION_v3 3
++struct wl_egl_window_v3 {
++    const intptr_t version;
++
++    int width;
++    int height;
++    int dx;
++    int dy;
++
++    int attached_width;
++    int attached_height;
++
++    void *driver_private;
++    void (*resize_callback)(struct wl_egl_window *, void *);
++    void (*destroy_window_callback)(void *);
++
++    struct wl_surface *surface;
++};
++
++
++/* This program checks we keep a backwards-compatible struct wl_egl_window
++ * definition whenever it is modified in wayland-egl-backend.h.
++ *
++ * The previous definition should be added above as a new struct
++ * wl_egl_window_vN, and the appropriate checks should be added below
++ */
++
++#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member)
++
++#define CHECK_RENAMED_MEMBER(a_ver, b_ver, a_member, b_member)                      \
++    do {                                                                            \
++        if (offsetof(struct wl_egl_window ## a_ver, a_member) !=                    \
++            offsetof(struct wl_egl_window ## b_ver, b_member)) {                    \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "offsetof(struct wl_egl_window" #a_ver "::" #a_member ") != "    \
++                   "offsetof(struct wl_egl_window" #b_ver "::" #b_member ")\n");    \
++            return 1;                                                               \
++        }                                                                           \
++                                                                                    \
++        if (MEMBER_SIZE(struct wl_egl_window ## a_ver, a_member) !=                 \
++            MEMBER_SIZE(struct wl_egl_window ## b_ver, b_member)) {                 \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "MEMBER_SIZE(struct wl_egl_window" #a_ver "::" #a_member ") != " \
++                   "MEMBER_SIZE(struct wl_egl_window" #b_ver "::" #b_member ")\n"); \
++            return 1;                                                               \
++        }                                                                           \
++    } while (0)
++
++#define CHECK_MEMBER(a_ver, b_ver, member) CHECK_RENAMED_MEMBER(a_ver, b_ver, member, member)
++#define CHECK_MEMBER_CURRENT(a_ver, member) CHECK_MEMBER(a_ver,, member)
++
++#define CHECK_SIZE(a_ver, b_ver)                                                    \
++    do {                                                                            \
++        if (sizeof(struct wl_egl_window ## a_ver) >                                 \
++            sizeof(struct wl_egl_window ## b_ver)) {                                \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "sizeof(struct wl_egl_window" #a_ver ") > "                      \
++                   "sizeof(struct wl_egl_window" #b_ver ")\n");                     \
++            return 1;                                                               \
++        }                                                                           \
++    } while (0)
++
++#define CHECK_SIZE_CURRENT(a_ver)                                                   \
++    do {                                                                            \
++        if (sizeof(struct wl_egl_window ## a_ver) !=                                \
++            sizeof(struct wl_egl_window)) {                                         \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "sizeof(struct wl_egl_window" #a_ver ") != "                     \
++                   "sizeof(struct wl_egl_window)\n");                               \
++            return 1;                                                               \
++        }                                                                           \
++    } while (0)
++
++#define CHECK_VERSION(a_ver, b_ver)                                                 \
++    do {                                                                            \
++        if ((WL_EGL_WINDOW_VERSION ## a_ver) >=                                     \
++            (WL_EGL_WINDOW_VERSION ## b_ver)) {                                     \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "WL_EGL_WINDOW_VERSION" #a_ver " >= "                            \
++                   "WL_EGL_WINDOW_VERSION" #b_ver "\n");                            \
++            return 1;                                                               \
++        }                                                                           \
++    } while (0)
++
++#define CHECK_VERSION_CURRENT(a_ver)                                                \
++    do {                                                                            \
++        if ((WL_EGL_WINDOW_VERSION ## a_ver) !=                                     \
++            (WL_EGL_WINDOW_VERSION)) {                                              \
++            printf("Backwards incompatible change detected!\n   "                    \
++                   "WL_EGL_WINDOW_VERSION" #a_ver " != "                            \
++                   "WL_EGL_WINDOW_VERSION\n");                                      \
++            return 1;                                                               \
++        }                                                                           \
++    } while (0)
++
++int main(int argc, char **argv)
++{
++    /* Check wl_egl_window_v1 ABI against wl_egl_window_v0 */
++    CHECK_MEMBER(_v0, _v1, surface);
++    CHECK_MEMBER(_v0, _v1, width);
++    CHECK_MEMBER(_v0, _v1, height);
++    CHECK_MEMBER(_v0, _v1, dx);
++    CHECK_MEMBER(_v0, _v1, dy);
++    CHECK_MEMBER(_v0, _v1, attached_width);
++    CHECK_MEMBER(_v0, _v1, attached_height);
++
++    CHECK_SIZE(_v0, _v1);
++
++    /* Check wl_egl_window_v2 ABI against wl_egl_window_v1 */
++    CHECK_MEMBER(_v1, _v2, surface);
++    CHECK_MEMBER(_v1, _v2, width);
++    CHECK_MEMBER(_v1, _v2, height);
++    CHECK_MEMBER(_v1, _v2, dx);
++    CHECK_MEMBER(_v1, _v2, dy);
++    CHECK_MEMBER(_v1, _v2, attached_width);
++    CHECK_MEMBER(_v1, _v2, attached_height);
++    CHECK_MEMBER(_v1, _v2, private);
++    CHECK_MEMBER(_v1, _v2, resize_callback);
++
++    CHECK_SIZE(_v1, _v2);
++
++    /* Check wl_egl_window_v3 ABI against wl_egl_window_v2 */
++    CHECK_RENAMED_MEMBER(_v2, _v3, surface, version);
++    CHECK_MEMBER        (_v2, _v3, width);
++    CHECK_MEMBER        (_v2, _v3, height);
++    CHECK_MEMBER        (_v2, _v3, dx);
++    CHECK_MEMBER        (_v2, _v3, dy);
++    CHECK_MEMBER        (_v2, _v3, attached_width);
++    CHECK_MEMBER        (_v2, _v3, attached_height);
++    CHECK_RENAMED_MEMBER(_v2, _v3, private, driver_private);
++    CHECK_MEMBER        (_v2, _v3, resize_callback);
++    CHECK_MEMBER        (_v2, _v3, destroy_window_callback);
++
++    CHECK_SIZE   (_v2, _v3);
++    CHECK_VERSION(_v2, _v3);
++
++    /* Check current wl_egl_window ABI against wl_egl_window_v3 */
++    CHECK_MEMBER_CURRENT(_v3, version);
++    CHECK_MEMBER_CURRENT(_v3, width);
++    CHECK_MEMBER_CURRENT(_v3, height);
++    CHECK_MEMBER_CURRENT(_v3, dx);
++    CHECK_MEMBER_CURRENT(_v3, dy);
++    CHECK_MEMBER_CURRENT(_v3, attached_width);
++    CHECK_MEMBER_CURRENT(_v3, attached_height);
++    CHECK_MEMBER_CURRENT(_v3, driver_private);
++    CHECK_MEMBER_CURRENT(_v3, resize_callback);
++    CHECK_MEMBER_CURRENT(_v3, destroy_window_callback);
++    CHECK_MEMBER_CURRENT(_v3, surface);
++
++    CHECK_SIZE_CURRENT   (_v3);
++    CHECK_VERSION_CURRENT(_v3);
++
++    return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e5287b766ba7a06ec3ed33b4bae5da418ad5934d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,67 @@@
++/*
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
++ */
++
++#ifndef _WAYLAND_EGL_PRIV_H
++#define _WAYLAND_EGL_PRIV_H
++
++#include <stdint.h>
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/*
++ * NOTE: This version must be kept in sync with the version field in the
++ * wayland-egl-backend pkgconfig file generated in meson.build.
++ */
++#define WL_EGL_WINDOW_VERSION 3
++
++struct wl_surface;
++
++struct wl_egl_window {
++      const intptr_t version;
++
++      int width;
++      int height;
++      int dx;
++      int dy;
++
++      int attached_width;
++      int attached_height;
++
++      void *driver_private;
++      void (*resize_callback)(struct wl_egl_window *, void *);
++      void (*destroy_window_callback)(void *);
++
++      struct wl_surface *surface;
++};
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b3ab5124de547b7004895ea1d89c27726f93ac65
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,59 @@@
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_EGL_CORE_H
++#define WAYLAND_EGL_CORE_H
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++#define WL_EGL_PLATFORM 1
++
++struct wl_egl_window;
++struct wl_surface;
++
++struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++                   int width, int height);
++
++void
++wl_egl_window_destroy(struct wl_egl_window *egl_window);
++
++void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++                   int width, int height,
++                   int dx, int dy);
++
++void
++wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
++                              int *width, int *height);
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d04fd042f43aabd4ac99a82c526531c817599965
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++#!/bin/sh
++set -eu
++
++RET=0
++LIB=${WAYLAND_EGL_LIB}
++
++if ! test -f "$LIB"; then
++      echo "Test binary \"$LIB\" does not exist"
++      exit 99
++fi
++
++if ! test -n "$NM"; then
++      echo "nm environment variable not set"
++      exit 99
++fi
++
++AVAIL_FUNCS="$($NM -D --format=bsd --defined-only $LIB | awk '{print $3}')"
++
++# Official ABI, taken from the header.
++REQ_FUNCS="wl_egl_window_resize
++wl_egl_window_create
++wl_egl_window_destroy
++wl_egl_window_get_attached_size
++"
++
++NEW_ABI=$(echo "$AVAIL_FUNCS" | while read func; do
++    echo "$func" | grep -q "^_" && continue
++    echo "$REQ_FUNCS" | grep -q "^$func$" && continue
++
++    echo $func
++done)
++
++if test -n "$NEW_ABI"; then
++      echo "New ABI detected - If intentional, update the test."
++      echo "$NEW_ABI"
++      RET=1
++fi
++
++REMOVED_ABI=$(echo "$REQ_FUNCS" | while read func; do
++    echo "$AVAIL_FUNCS" | grep -q "^$func$" && continue
++
++    echo $func
++done)
++
++if test -n "$REMOVED_ABI"; then
++      echo "ABI break detected - Required symbol(s) no longer exported!"
++      echo "$REMOVED_ABI"
++      RET=1
++fi
++
++exit $RET
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..36a347128b8f9662ffe0162c442a5c6aedf8ac86
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,118 @@@
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining a
++ * copy of this software and associated documentation files (the "Software"),
++ * to deal in the Software without restriction, including without limitation
++ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
++ * and/or sell copies of the Software, and to permit persons to whom the
++ * Software is furnished to do so, subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the next
++ * paragraph) shall be included in all copies or substantial portions of the
++ * Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
++ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
++ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
++ * DEALINGS IN THE SOFTWARE.
++ *
++ * Authors:
++ *    Kristian Høgsberg <krh@bitplanet.net>
++ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
++ */
++
++#include <stdlib.h>
++#include <string.h>
++
++#include "wayland-egl.h"
++#include "wayland-egl-backend.h"
++#include "wayland-util.h"
++
++
++/** Resize the EGL window
++ *
++ * \param egl_window A pointer to a struct wl_egl_window
++ * \param width The new width
++ * \param height The new height
++ * \param dx Offset on the X axis
++ * \param dy Offset on the Y axis
++ *
++ * Note that applications should prefer using the wl_surface.offset request if
++ * the associated wl_surface has the interface version 5 or higher.
++ *
++ * If the wl_surface.offset request is used, applications MUST pass 0 to both
++ * dx and dy.
++ */
++WL_EXPORT void
++wl_egl_window_resize(struct wl_egl_window *egl_window,
++                   int width, int height,
++                   int dx, int dy)
++{
++      if (width <= 0 || height <= 0)
++              return;
++
++      egl_window->width  = width;
++      egl_window->height = height;
++      egl_window->dx     = dx;
++      egl_window->dy     = dy;
++
++      if (egl_window->resize_callback)
++              egl_window->resize_callback(egl_window, egl_window->driver_private);
++}
++
++WL_EXPORT struct wl_egl_window *
++wl_egl_window_create(struct wl_surface *surface,
++                   int width, int height)
++{
++      struct wl_egl_window *egl_window;
++
++      if (width <= 0 || height <= 0)
++              return NULL;
++
++      egl_window = calloc(1, sizeof *egl_window);
++      if (!egl_window)
++              return NULL;
++
++      /* Cast away the constness to set the version number.
++       *
++       * We want the const notation since it gives an explicit
++       * feedback to the backend implementation, should it try to
++       * change it.
++       *
++       * The latter in itself is not too surprising as these days APIs
++       * tend to provide bidirectional version field.
++       */
++      intptr_t *version = (intptr_t *)&egl_window->version;
++      *version = WL_EGL_WINDOW_VERSION;
++
++      egl_window->surface = surface;
++
++      egl_window->width  = width;
++      egl_window->height = height;
++
++      return egl_window;
++}
++
++WL_EXPORT void
++wl_egl_window_destroy(struct wl_egl_window *egl_window)
++{
++      if (egl_window->destroy_window_callback)
++              egl_window->destroy_window_callback(egl_window->driver_private);
++      free(egl_window);
++}
++
++WL_EXPORT void
++wl_egl_window_get_attached_size(struct wl_egl_window *egl_window,
++                              int *width, int *height)
++{
++      if (width)
++              *width = egl_window->attached_width;
++      if (height)
++              *height = egl_window->attached_height;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..279dcb8bb8d2d13a1783445ea152799ca690270a
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,33 @@@
++/*
++ * Copyright © 2011 Kristian Høgsberg
++ * Copyright © 2011 Benjamin Franzke
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_EGL_H
++#define WAYLAND_EGL_H
++
++#include <wayland-client.h>
++#include "wayland-egl-core.h"
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f469756f2abdb70744c2410881581c75a0992007
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,140 @@@
++project(
++      'wayland', 'c',
++      version: '1.21.90',
++      license: 'MIT',
++      meson_version: '>= 0.56.0',
++      default_options: [
++              'warning_level=2',
++              'buildtype=debugoptimized',
++              'c_std=c99',
++      ]
++)
++wayland_version = meson.project_version().split('.')
++
++config_h = configuration_data()
++config_h.set_quoted('PACKAGE', meson.project_name())
++config_h.set_quoted('PACKAGE_VERSION', meson.project_version())
++
++cc_args = []
++if host_machine.system() != 'freebsd'
++      cc_args += ['-D_POSIX_C_SOURCE=200809L']
++endif
++add_project_arguments(cc_args, language: 'c')
++
++compiler_flags = [
++      '-Wno-unused-parameter',
++      '-Wstrict-prototypes',
++      '-Wmissing-prototypes',
++      '-fvisibility=hidden',
++]
++
++cc = meson.get_compiler('c')
++add_project_arguments(
++      cc.get_supported_arguments(compiler_flags),
++      language: 'c'
++)
++
++foreach h: [ 'sys/prctl.h', 'sys/procctl.h', 'sys/ucred.h' ]
++      config_h.set('HAVE_' + h.underscorify().to_upper(), cc.has_header(h))
++endforeach
++
++have_funcs = [
++      'accept4',
++      'mkostemp',
++      'posix_fallocate',
++      'prctl',
++      'memfd_create',
++      'mremap',
++      'strndup',
++]
++foreach f: have_funcs
++      config_h.set('HAVE_' + f.underscorify().to_upper(), cc.has_function(f))
++endforeach
++config_h.set10('HAVE_XUCRED_CR_PID', cc.has_member('struct xucred', 'cr_pid', prefix : '#include <sys/ucred.h>'))
++have_broken_msg_cmsg_cloexec = false
++if host_machine.system() == 'freebsd'
++      have_broken_msg_cmsg_cloexec = not cc.compiles('''
++#include <sys/param.h> /* To get __FreeBSD_version. */
++#if __FreeBSD_version < 1300502 || \
++    (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400006)
++/*
++ * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015 and
++ * 2021. Check if we are compiling against a version that includes the fix
++ * (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
++ */
++#error "Broken MSG_CMSG_CLOEXEC"
++#endif
++''', name : 'MSG_CMSG_CLOEXEC works correctly')
++endif
++config_h.set10('HAVE_BROKEN_MSG_CMSG_CLOEXEC', have_broken_msg_cmsg_cloexec)
++
++if get_option('libraries')
++      if host_machine.system() == 'freebsd'
++              # When building for FreeBSD, epoll(7) is provided by a userspace
++              # wrapper around kqueue(2).
++              epoll_dep = dependency('epoll-shim')
++      else
++              # Otherwise, assume that epoll(7) is supported natively.
++              epoll_dep = []
++      endif
++      ffi_dep = dependency('libffi')
++
++      decls = [
++              { 'header': 'sys/signalfd.h', 'symbol': 'SFD_CLOEXEC' },
++              { 'header': 'sys/timerfd.h', 'symbol': 'TFD_CLOEXEC' },
++              { 'header': 'time.h', 'symbol': 'CLOCK_MONOTONIC' },
++      ]
++
++      foreach d: decls
++              if not cc.has_header_symbol(d['header'], d['symbol'], dependencies: epoll_dep, args: cc_args)
++                      error('@0@ is needed to compile Wayland libraries'.format(d['symbol']))
++              endif
++      endforeach
++
++      rt_dep = []
++      if not cc.has_function('clock_gettime', prefix: '#include <time.h>')
++              rt_dep = cc.find_library('rt')
++              if not cc.has_function('clock_gettime', prefix: '#include <time.h>', dependencies: rt_dep, args: cc_args)
++                      error('clock_gettime not found')
++              endif
++      endif
++endif
++
++configure_file(
++      output: 'config.h',
++      configuration: config_h,
++)
++
++pkgconfig = import('pkgconfig')
++
++wayland_protocol_xml = files('protocol/wayland.xml')
++
++root_inc = include_directories('.')
++protocol_inc = include_directories('protocol')
++src_inc = include_directories('src')
++
++subdir('src')
++
++if get_option('libraries')
++      subdir('cursor')
++      subdir('egl')
++endif
++if get_option('tests')
++      subdir('tests')
++endif
++if get_option('documentation')
++      subdir('doc')
++endif
++
++if get_option('scanner')
++      install_data([
++              'wayland-scanner.mk',
++              'protocol/wayland.xml',
++              'protocol/wayland.dtd',
++      ])
++
++      install_data(
++              [ 'wayland-scanner.m4' ],
++              install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'aclocal'),
++      )
++endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..b8e2ec60bdc82ba41bd7ce3d1c8f76d271166b8d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,24 @@@
++option('libraries',
++  description: 'Compile Wayland libraries',
++  type: 'boolean',
++  value: true)
++option('scanner',
++  description: 'Compile wayland-scanner binary',
++  type: 'boolean',
++  value: true)
++option('tests',
++  description: 'Compile Wayland tests',
++  type: 'boolean',
++  value: true)
++option('documentation',
++  description: 'Build the documentation (requires Doxygen, dot, xmlto, xsltproc)',
++  type: 'boolean',
++  value: true)
++option('dtd_validation',
++  description: 'Validate the protocol DTD (requires libxml2)',
++  type: 'boolean',
++  value: true)
++option('icon_directory',
++  description: 'Location used to look for cursors (defaults to ${datadir}/icons if unset)',
++  type: 'string',
++  value: '')
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..78f49d269391764b3f3a620fd1ae5e4553e41921
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++wayland.html
++.wayland.xml.valid
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c56642e198b6e0e3eed5d555eee3187605ae7fea
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,153 @@@
++#!/usr/bin/env python3
++
++# This script synchronizes wayland.xml's wl_shm.format enum with drm_fourcc.h.
++# Invoke it to update wayland.xml, then manually check the changes applied.
++#
++# Requires Python 3, python-lxml, a C compiler and pkg-config.
++
++import os
++import subprocess
++import sys
++import tempfile
++# We need lxml instead of the standard library because we want
++# Element.sourceline
++from lxml import etree as ElementTree
++
++proto_dir = os.path.dirname(os.path.realpath(__file__))
++wayland_proto = proto_dir + "/wayland.xml"
++
++cc = os.getenv("CC", "cc")
++pkg_config = os.getenv("PKG_CONFIG", "pkg-config")
++
++# Find drm_fourcc.h
++version = subprocess.check_output([pkg_config, "libdrm",
++    "--modversion"]).decode().strip()
++cflags = subprocess.check_output([pkg_config, "libdrm",
++    "--cflags-only-I"]).decode().strip().split()
++libdrm_include = None
++for include_flag in cflags:
++    if not include_flag.startswith("-I"):
++        raise Exception("Expected one include dir for libdrm")
++    include_dir = include_flag[2:]
++    if include_dir.endswith("/libdrm"):
++        libdrm_include = include_dir
++        fourcc_include = libdrm_include + "/drm_fourcc.h"
++if libdrm_include == None:
++    raise Exception("Failed to find libdrm include dir")
++
++print("Using libdrm " + version, file=sys.stderr)
++
++def drm_format_to_wl(ident):
++    return ident.replace("DRM_FORMAT_", "").lower()
++
++# Collect DRM format constant names
++ident_list = []
++descriptions = {}
++prev_comment = None
++with open(fourcc_include) as input_file:
++    for l in input_file.readlines():
++        l = l.strip()
++
++        # Collect comments right before format definitions
++        if l.startswith("/*") and l.endswith("*/"):
++            prev_comment = l[2:-2]
++            continue
++        desc = prev_comment
++        prev_comment = None
++
++        # Recognize format definitions
++        parts = l.split()
++        if len(parts) < 3 or parts[0] != "#define":
++            continue
++        ident = parts[1]
++        if not ident.startswith("DRM_FORMAT_") or ident.startswith(
++                "DRM_FORMAT_MOD_"):
++            continue
++
++        ident_list.append(ident)
++
++        # Prefer in-line comments
++        if l.endswith("*/"):
++            desc = l[l.rfind("/*") + 2:-2]
++        if desc != None:
++            descriptions[drm_format_to_wl(ident)] = desc.strip()
++
++# Collect DRM format values
++idents = {}
++with tempfile.TemporaryDirectory() as work_dir:
++    c_file_name = work_dir + "/print-formats.c"
++    exe_file_name = work_dir + "/print-formats"
++
++    with open(c_file_name, "w+") as c_file:
++        c_file.write('#include <inttypes.h>\n')
++        c_file.write('#include <stdint.h>\n')
++        c_file.write('#include <stdio.h>\n')
++        c_file.write('#include <drm_fourcc.h>\n')
++        c_file.write('\n')
++        c_file.write('int main(void) {\n')
++        for ident in ident_list:
++            c_file.write('printf("0x%" PRIX64 "\\n", (uint64_t)' + ident + ');\n')
++        c_file.write('}\n')
++
++    subprocess.check_call([cc, "-Wall", "-Wextra", "-o", exe_file_name,
++        c_file_name] + cflags)
++    output = subprocess.check_output([exe_file_name]).decode().strip()
++    for i, val in enumerate(output.splitlines()):
++        idents[ident_list[i]] = val
++
++# We don't need those
++del idents["DRM_FORMAT_BIG_ENDIAN"]
++del idents["DRM_FORMAT_INVALID"]
++del idents["DRM_FORMAT_RESERVED"]
++
++# Convert from DRM constants to Wayland wl_shm.format entries
++formats = {}
++for ident, val in idents.items():
++    formats[drm_format_to_wl(ident)] = val.lower()
++# Special case for ARGB8888 and XRGB8888
++formats["argb8888"] = "0"
++formats["xrgb8888"] = "1"
++
++print("Loaded {} formats from drm_fourcc.h".format(len(formats)), file=sys.stderr)
++
++tree = ElementTree.parse("wayland.xml")
++root = tree.getroot()
++wl_shm_format = root.find("./interface[@name='wl_shm']/enum[@name='format']")
++if wl_shm_format == None:
++    raise Exception("wl_shm.format not found in wayland.xml")
++
++# Remove formats we already know about
++last_line = None
++for node in wl_shm_format:
++    if node.tag != "entry":
++        continue
++    fmt = node.attrib["name"]
++    val = node.attrib["value"]
++    if fmt not in formats:
++        raise Exception("Format present in wl_shm.formats but not in "
++            "drm_fourcc.h: " + fmt)
++    if val != formats[fmt]:
++        raise Exception("Format value in wl_shm.formats ({}) differs "
++            "from value in drm_fourcc.h ({}) for format {}"
++            .format(val, formats[fmt], fmt))
++    del formats[fmt]
++    last_line = node.sourceline
++if last_line == None:
++    raise Exception("Expected at least one existing wl_shm.format entry")
++
++print("Adding {} formats to wayland.xml...".format(len(formats)), file=sys.stderr)
++
++# Append new formats
++new_wayland_proto = wayland_proto + ".new"
++with open(new_wayland_proto, "w+") as output_file, \
++        open(wayland_proto) as input_file:
++    for i, l in enumerate(input_file.readlines()):
++        output_file.write(l)
++        if i + 1 == last_line:
++            for fmt, val in formats.items():
++                output_file.write('      <entry name="{}" value="{}"'
++                    .format(fmt, val))
++                if fmt in descriptions:
++                    output_file.write(' summary="{}"'.format(descriptions[fmt]))
++                output_file.write('/>\n')
++os.rename(new_wayland_proto, wayland_proto)
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..22d80a10ef98fb8ad5934d41302f94725af11132
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,52 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="build_time_wayland_tests">
++
++  <copyright>
++    Copyright © 2017 Samsung Electronics Co., Ltd
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <interface name="fd_passer" version="2">
++    <description summary="Sends an event with an fd">
++      A trivial interface for fd passing tests.
++    </description>
++
++    <request name="destroy" type="destructor"/>
++
++    <event name="pre_fd"/>
++
++    <event name="fd">
++      <description summary="passes a file descriptor"/>
++      <arg name="fd" type="fd" summary="file descriptor"/>
++    </event>
++
++    <!-- Version 2 additions -->
++    <request name="conjoin" since="2">
++      <description summary="register another fd passer with this one">
++      Tells this fd passer object about another one to send events
++      to for more complicated fd leak tests.
++      </description>
++      <arg name="passer" type="object" interface="fd_passer"/>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ee062eeab46fa9c57896ab449000dfd9345dcf54
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,32 @@@
++<!ELEMENT protocol (copyright?, description?, interface+)>
++  <!ATTLIST protocol name CDATA #REQUIRED>
++<!ELEMENT copyright (#PCDATA)>
++<!ELEMENT interface (description?,(request|event|enum)+)>
++  <!ATTLIST interface name CDATA #REQUIRED>
++  <!ATTLIST interface version CDATA #REQUIRED>
++<!ELEMENT request (description?,arg*)>
++  <!ATTLIST request name CDATA #REQUIRED>
++  <!ATTLIST request type CDATA #IMPLIED>
++  <!ATTLIST request since CDATA #IMPLIED>
++<!ELEMENT event (description?,arg*)>
++  <!ATTLIST event name CDATA #REQUIRED>
++  <!ATTLIST event type CDATA #IMPLIED>
++  <!ATTLIST event since CDATA #IMPLIED>
++<!ELEMENT enum (description?,entry*)>
++  <!ATTLIST enum name CDATA #REQUIRED>
++  <!ATTLIST enum since CDATA #IMPLIED>
++  <!ATTLIST enum bitfield CDATA #IMPLIED>
++<!ELEMENT entry (description?)>
++  <!ATTLIST entry name CDATA #REQUIRED>
++  <!ATTLIST entry value CDATA #REQUIRED>
++  <!ATTLIST entry summary CDATA #IMPLIED>
++  <!ATTLIST entry since CDATA #IMPLIED>
++<!ELEMENT arg (description?)>
++  <!ATTLIST arg name CDATA #REQUIRED>
++  <!ATTLIST arg type CDATA #REQUIRED>
++  <!ATTLIST arg summary CDATA #IMPLIED>
++  <!ATTLIST arg interface CDATA #IMPLIED>
++  <!ATTLIST arg allow-null CDATA #IMPLIED>
++  <!ATTLIST arg enum CDATA #IMPLIED>
++<!ELEMENT description (#PCDATA)>
++  <!ATTLIST description summary CDATA #REQUIRED>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..10781cf1679492ee30529d07929b28abe7ebeaed
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,3058 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wayland">
++
++  <copyright>
++    Copyright © 2008-2011 Kristian Høgsberg
++    Copyright © 2010-2011 Intel Corporation
++    Copyright © 2012-2013 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <interface name="wl_display" version="1">
++    <description summary="core global object">
++      The core global object.  This is a special singleton object.  It
++      is used for internal Wayland protocol features.
++    </description>
++
++    <request name="sync">
++      <description summary="asynchronous roundtrip">
++      The sync request asks the server to emit the 'done' event
++      on the returned wl_callback object.  Since requests are
++      handled in-order and events are delivered in-order, this can
++      be used as a barrier to ensure all previous requests and the
++      resulting events have been handled.
++
++      The object returned by this request will be destroyed by the
++      compositor after the callback is fired and as such the client must not
++      attempt to use it after that point.
++
++      The callback_data passed in the callback is the event serial.
++      </description>
++      <arg name="callback" type="new_id" interface="wl_callback"
++         summary="callback object for the sync request"/>
++    </request>
++
++    <request name="get_registry">
++      <description summary="get global registry object">
++      This request creates a registry object that allows the client
++      to list and bind the global objects available from the
++      compositor.
++
++      It should be noted that the server side resources consumed in
++      response to a get_registry request can only be released when the
++      client disconnects, not when the client side proxy is destroyed.
++      Therefore, clients should invoke get_registry as infrequently as
++      possible to avoid wasting memory.
++      </description>
++      <arg name="registry" type="new_id" interface="wl_registry"
++         summary="global registry object"/>
++    </request>
++
++    <event name="error">
++      <description summary="fatal error event">
++      The error event is sent out when a fatal (non-recoverable)
++      error has occurred.  The object_id argument is the object
++      where the error occurred, most often in response to a request
++      to that object.  The code identifies the error and is defined
++      by the object interface.  As such, each interface defines its
++      own set of error codes.  The message is a brief description
++      of the error, for (debugging) convenience.
++      </description>
++      <arg name="object_id" type="object" summary="object where the error occurred"/>
++      <arg name="code" type="uint" summary="error code"/>
++      <arg name="message" type="string" summary="error description"/>
++    </event>
++
++    <enum name="error">
++      <description summary="global error values">
++      These errors are global and can be emitted in response to any
++      server request.
++      </description>
++      <entry name="invalid_object" value="0"
++           summary="server couldn't find object"/>
++      <entry name="invalid_method" value="1"
++           summary="method doesn't exist on the specified interface or malformed request"/>
++      <entry name="no_memory" value="2"
++           summary="server is out of memory"/>
++      <entry name="implementation" value="3"
++           summary="implementation error in compositor"/>
++    </enum>
++
++    <event name="delete_id">
++      <description summary="acknowledge object ID deletion">
++      This event is used internally by the object ID management
++      logic. When a client deletes an object that it had created,
++      the server will send this event to acknowledge that it has
++      seen the delete request. When the client receives this event,
++      it will know that it can safely reuse the object ID.
++      </description>
++      <arg name="id" type="uint" summary="deleted object ID"/>
++    </event>
++  </interface>
++
++  <interface name="wl_registry" version="1">
++    <description summary="global registry object">
++      The singleton global registry object.  The server has a number of
++      global objects that are available to all clients.  These objects
++      typically represent an actual object in the server (for example,
++      an input device) or they are singleton objects that provide
++      extension functionality.
++
++      When a client creates a registry object, the registry object
++      will emit a global event for each global currently in the
++      registry.  Globals come and go as a result of device or
++      monitor hotplugs, reconfiguration or other events, and the
++      registry will send out global and global_remove events to
++      keep the client up to date with the changes.  To mark the end
++      of the initial burst of events, the client can use the
++      wl_display.sync request immediately after calling
++      wl_display.get_registry.
++
++      A client can bind to a global object by using the bind
++      request.  This creates a client-side handle that lets the object
++      emit events to the client and lets the client invoke requests on
++      the object.
++    </description>
++
++    <request name="bind">
++      <description summary="bind an object to the display">
++      Binds a new, client-created object to the server using the
++      specified name as the identifier.
++      </description>
++      <arg name="name" type="uint" summary="unique numeric name of the object"/>
++      <arg name="id" type="new_id" summary="bounded object"/>
++    </request>
++
++    <event name="global">
++      <description summary="announce global object">
++      Notify the client of global objects.
++
++      The event notifies the client that a global object with
++      the given name is now available, and it implements the
++      given version of the given interface.
++      </description>
++      <arg name="name" type="uint" summary="numeric name of the global object"/>
++      <arg name="interface" type="string" summary="interface implemented by the object"/>
++      <arg name="version" type="uint" summary="interface version"/>
++    </event>
++
++    <event name="global_remove">
++      <description summary="announce removal of global object">
++      Notify the client of removed global objects.
++
++      This event notifies the client that the global identified
++      by name is no longer available.  If the client bound to
++      the global using the bind request, the client should now
++      destroy that object.
++
++      The object remains valid and requests to the object will be
++      ignored until the client destroys it, to avoid races between
++      the global going away and a client sending a request to it.
++      </description>
++      <arg name="name" type="uint" summary="numeric name of the global object"/>
++    </event>
++  </interface>
++
++  <interface name="wl_callback" version="1">
++    <description summary="callback object">
++      Clients can handle the 'done' event to get notified when
++      the related request is done.
++    </description>
++
++    <event name="done" type="destructor">
++      <description summary="done event">
++      Notify the client when the related request is done.
++      </description>
++      <arg name="callback_data" type="uint" summary="request-specific data for the callback"/>
++    </event>
++  </interface>
++
++  <interface name="wl_compositor" version="5">
++    <description summary="the compositor singleton">
++      A compositor.  This object is a singleton global.  The
++      compositor is in charge of combining the contents of multiple
++      surfaces into one displayable output.
++    </description>
++
++    <request name="create_surface">
++      <description summary="create new surface">
++      Ask the compositor to create a new surface.
++      </description>
++      <arg name="id" type="new_id" interface="wl_surface" summary="the new surface"/>
++    </request>
++
++    <request name="create_region">
++      <description summary="create new region">
++      Ask the compositor to create a new region.
++      </description>
++      <arg name="id" type="new_id" interface="wl_region" summary="the new region"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shm_pool" version="1">
++    <description summary="a shared memory pool">
++      The wl_shm_pool object encapsulates a piece of memory shared
++      between the compositor and client.  Through the wl_shm_pool
++      object, the client can allocate shared memory wl_buffer objects.
++      All objects created through the same pool share the same
++      underlying mapped memory. Reusing the mapped memory avoids the
++      setup/teardown overhead and is useful when interactively resizing
++      a surface or for many small buffers.
++    </description>
++
++    <request name="create_buffer">
++      <description summary="create a buffer from the pool">
++      Create a wl_buffer object from the pool.
++
++      The buffer is created offset bytes into the pool and has
++      width and height as specified.  The stride argument specifies
++      the number of bytes from the beginning of one row to the beginning
++      of the next.  The format is the pixel format of the buffer and
++      must be one of those advertised through the wl_shm.format event.
++
++      A buffer will keep a reference to the pool it was created from
++      so it is valid to destroy the pool immediately after creating
++      a buffer from it.
++      </description>
++      <arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
++      <arg name="offset" type="int" summary="buffer byte offset within the pool"/>
++      <arg name="width" type="int" summary="buffer width, in pixels"/>
++      <arg name="height" type="int" summary="buffer height, in pixels"/>
++      <arg name="stride" type="int" summary="number of bytes from the beginning of one row to the beginning of the next row"/>
++      <arg name="format" type="uint" enum="wl_shm.format" summary="buffer pixel format"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pool">
++      Destroy the shared memory pool.
++
++      The mmapped memory will be released when all
++      buffers that have been created from this pool
++      are gone.
++      </description>
++    </request>
++
++    <request name="resize">
++      <description summary="change the size of the pool mapping">
++      This request will cause the server to remap the backing memory
++      for the pool from the file descriptor passed when the pool was
++      created, but using the new size.  This request can only be
++      used to make the pool bigger.
++
++        This request only changes the amount of bytes that are mmapped
++        by the server and does not touch the file corresponding to the
++        file descriptor passed at creation time. It is the client's
++        responsibility to ensure that the file is at least as big as
++        the new pool size.
++      </description>
++      <arg name="size" type="int" summary="new size of the pool, in bytes"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shm" version="1">
++    <description summary="shared memory support">
++      A singleton global object that provides support for shared
++      memory.
++
++      Clients can create wl_shm_pool objects using the create_pool
++      request.
++
++      On binding the wl_shm object one or more format events
++      are emitted to inform clients about the valid pixel formats
++      that can be used for buffers.
++    </description>
++
++    <enum name="error">
++      <description summary="wl_shm error values">
++      These errors can be emitted in response to wl_shm requests.
++      </description>
++      <entry name="invalid_format" value="0" summary="buffer format is not known"/>
++      <entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
++      <entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
++    </enum>
++
++    <enum name="format">
++      <description summary="pixel formats">
++      This describes the memory layout of an individual pixel.
++
++      All renderers should support argb8888 and xrgb8888 but any other
++      formats are optional and may not be supported by the particular
++      renderer in use.
++
++      The drm format codes match the macros defined in drm_fourcc.h, except
++      argb8888 and xrgb8888. The formats actually supported by the compositor
++      will be reported by the format event.
++
++      For all wl_shm formats and unless specified in another protocol
++      extension, pre-multiplied alpha is used for pixel values.
++      </description>
++      <!-- Note to protocol writers: don't update this list manually, instead
++         run the automated script that keeps it in sync with drm_fourcc.h. -->
++      <entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
++      <entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
++      <entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
++      <entry name="rgb332" value="0x38424752" summary="8-bit RGB format, [7:0] R:G:B 3:3:2"/>
++      <entry name="bgr233" value="0x38524742" summary="8-bit BGR format, [7:0] B:G:R 2:3:3"/>
++      <entry name="xrgb4444" value="0x32315258" summary="16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian"/>
++      <entry name="xbgr4444" value="0x32314258" summary="16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian"/>
++      <entry name="rgbx4444" value="0x32315852" summary="16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian"/>
++      <entry name="bgrx4444" value="0x32315842" summary="16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian"/>
++      <entry name="argb4444" value="0x32315241" summary="16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian"/>
++      <entry name="abgr4444" value="0x32314241" summary="16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian"/>
++      <entry name="rgba4444" value="0x32314152" summary="16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
++      <entry name="bgra4444" value="0x32314142" summary="16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian"/>
++      <entry name="xrgb1555" value="0x35315258" summary="16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian"/>
++      <entry name="xbgr1555" value="0x35314258" summary="16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian"/>
++      <entry name="rgbx5551" value="0x35315852" summary="16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian"/>
++      <entry name="bgrx5551" value="0x35315842" summary="16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian"/>
++      <entry name="argb1555" value="0x35315241" summary="16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian"/>
++      <entry name="abgr1555" value="0x35314241" summary="16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian"/>
++      <entry name="rgba5551" value="0x35314152" summary="16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian"/>
++      <entry name="bgra5551" value="0x35314142" summary="16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian"/>
++      <entry name="rgb565" value="0x36314752" summary="16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian"/>
++      <entry name="bgr565" value="0x36314742" summary="16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian"/>
++      <entry name="rgb888" value="0x34324752" summary="24-bit RGB format, [23:0] R:G:B little endian"/>
++      <entry name="bgr888" value="0x34324742" summary="24-bit BGR format, [23:0] B:G:R little endian"/>
++      <entry name="xbgr8888" value="0x34324258" summary="32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian"/>
++      <entry name="rgbx8888" value="0x34325852" summary="32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian"/>
++      <entry name="bgrx8888" value="0x34325842" summary="32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian"/>
++      <entry name="abgr8888" value="0x34324241" summary="32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian"/>
++      <entry name="rgba8888" value="0x34324152" summary="32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian"/>
++      <entry name="bgra8888" value="0x34324142" summary="32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian"/>
++      <entry name="xrgb2101010" value="0x30335258" summary="32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian"/>
++      <entry name="xbgr2101010" value="0x30334258" summary="32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian"/>
++      <entry name="rgbx1010102" value="0x30335852" summary="32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian"/>
++      <entry name="bgrx1010102" value="0x30335842" summary="32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian"/>
++      <entry name="argb2101010" value="0x30335241" summary="32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian"/>
++      <entry name="abgr2101010" value="0x30334241" summary="32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian"/>
++      <entry name="rgba1010102" value="0x30334152" summary="32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian"/>
++      <entry name="bgra1010102" value="0x30334142" summary="32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian"/>
++      <entry name="yuyv" value="0x56595559" summary="packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian"/>
++      <entry name="yvyu" value="0x55595659" summary="packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian"/>
++      <entry name="uyvy" value="0x59565955" summary="packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian"/>
++      <entry name="vyuy" value="0x59555956" summary="packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian"/>
++      <entry name="ayuv" value="0x56555941" summary="packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian"/>
++      <entry name="nv12" value="0x3231564e" summary="2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane"/>
++      <entry name="nv21" value="0x3132564e" summary="2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane"/>
++      <entry name="nv16" value="0x3631564e" summary="2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane"/>
++      <entry name="nv61" value="0x3136564e" summary="2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane"/>
++      <entry name="yuv410" value="0x39565559" summary="3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu410" value="0x39555659" summary="3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv411" value="0x31315559" summary="3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu411" value="0x31315659" summary="3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv420" value="0x32315559" summary="3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu420" value="0x32315659" summary="3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv422" value="0x36315559" summary="3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu422" value="0x36315659" summary="3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv444" value="0x34325559" summary="3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu444" value="0x34325659" summary="3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="r8" value="0x20203852" summary="[7:0] R"/>
++      <entry name="r16" value="0x20363152" summary="[15:0] R little endian"/>
++      <entry name="rg88" value="0x38384752" summary="[15:0] R:G 8:8 little endian"/>
++      <entry name="gr88" value="0x38385247" summary="[15:0] G:R 8:8 little endian"/>
++      <entry name="rg1616" value="0x32334752" summary="[31:0] R:G 16:16 little endian"/>
++      <entry name="gr1616" value="0x32335247" summary="[31:0] G:R 16:16 little endian"/>
++      <entry name="xrgb16161616f" value="0x48345258" summary="[63:0] x:R:G:B 16:16:16:16 little endian"/>
++      <entry name="xbgr16161616f" value="0x48344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
++      <entry name="argb16161616f" value="0x48345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
++      <entry name="abgr16161616f" value="0x48344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
++      <entry name="xyuv8888" value="0x56555958" summary="[31:0] X:Y:Cb:Cr 8:8:8:8 little endian"/>
++      <entry name="vuy888" value="0x34325556" summary="[23:0] Cr:Cb:Y 8:8:8 little endian"/>
++      <entry name="vuy101010" value="0x30335556" summary="Y followed by U then V, 10:10:10. Non-linear modifier only"/>
++      <entry name="y210" value="0x30313259" summary="[63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 10:6:10:6:10:6:10:6 little endian per 2 Y pixels"/>
++      <entry name="y212" value="0x32313259" summary="[63:0] Cr0:0:Y1:0:Cb0:0:Y0:0 12:4:12:4:12:4:12:4 little endian per 2 Y pixels"/>
++      <entry name="y216" value="0x36313259" summary="[63:0] Cr0:Y1:Cb0:Y0 16:16:16:16 little endian per 2 Y pixels"/>
++      <entry name="y410" value="0x30313459" summary="[31:0] A:Cr:Y:Cb 2:10:10:10 little endian"/>
++      <entry name="y412" value="0x32313459" summary="[63:0] A:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian"/>
++      <entry name="y416" value="0x36313459" summary="[63:0] A:Cr:Y:Cb 16:16:16:16 little endian"/>
++      <entry name="xvyu2101010" value="0x30335658" summary="[31:0] X:Cr:Y:Cb 2:10:10:10 little endian"/>
++      <entry name="xvyu12_16161616" value="0x36335658" summary="[63:0] X:0:Cr:0:Y:0:Cb:0 12:4:12:4:12:4:12:4 little endian"/>
++      <entry name="xvyu16161616" value="0x38345658" summary="[63:0] X:Cr:Y:Cb 16:16:16:16 little endian"/>
++      <entry name="y0l0" value="0x304c3059" summary="[63:0]   A3:A2:Y3:0:Cr0:0:Y2:0:A1:A0:Y1:0:Cb0:0:Y0:0  1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian"/>
++      <entry name="x0l0" value="0x304c3058" summary="[63:0]   X3:X2:Y3:0:Cr0:0:Y2:0:X1:X0:Y1:0:Cb0:0:Y0:0  1:1:8:2:8:2:8:2:1:1:8:2:8:2:8:2 little endian"/>
++      <entry name="y0l2" value="0x324c3059" summary="[63:0]   A3:A2:Y3:Cr0:Y2:A1:A0:Y1:Cb0:Y0  1:1:10:10:10:1:1:10:10:10 little endian"/>
++      <entry name="x0l2" value="0x324c3058" summary="[63:0]   X3:X2:Y3:Cr0:Y2:X1:X0:Y1:Cb0:Y0  1:1:10:10:10:1:1:10:10:10 little endian"/>
++      <entry name="yuv420_8bit" value="0x38305559"/>
++      <entry name="yuv420_10bit" value="0x30315559"/>
++      <entry name="xrgb8888_a8" value="0x38415258"/>
++      <entry name="xbgr8888_a8" value="0x38414258"/>
++      <entry name="rgbx8888_a8" value="0x38415852"/>
++      <entry name="bgrx8888_a8" value="0x38415842"/>
++      <entry name="rgb888_a8" value="0x38413852"/>
++      <entry name="bgr888_a8" value="0x38413842"/>
++      <entry name="rgb565_a8" value="0x38413552"/>
++      <entry name="bgr565_a8" value="0x38413542"/>
++      <entry name="nv24" value="0x3432564e" summary="non-subsampled Cr:Cb plane"/>
++      <entry name="nv42" value="0x3234564e" summary="non-subsampled Cb:Cr plane"/>
++      <entry name="p210" value="0x30313250" summary="2x1 subsampled Cr:Cb plane, 10 bit per channel"/>
++      <entry name="p010" value="0x30313050" summary="2x2 subsampled Cr:Cb plane 10 bits per channel"/>
++      <entry name="p012" value="0x32313050" summary="2x2 subsampled Cr:Cb plane 12 bits per channel"/>
++      <entry name="p016" value="0x36313050" summary="2x2 subsampled Cr:Cb plane 16 bits per channel"/>
++      <entry name="axbxgxrx106106106106" value="0x30314241" summary="[63:0] A:x:B:x:G:x:R:x 10:6:10:6:10:6:10:6 little endian"/>
++      <entry name="nv15" value="0x3531564e" summary="2x2 subsampled Cr:Cb plane"/>
++      <entry name="q410" value="0x30313451"/>
++      <entry name="q401" value="0x31303451"/>
++      <entry name="xrgb16161616" value="0x38345258" summary="[63:0] x:R:G:B 16:16:16:16 little endian"/>
++      <entry name="xbgr16161616" value="0x38344258" summary="[63:0] x:B:G:R 16:16:16:16 little endian"/>
++      <entry name="argb16161616" value="0x38345241" summary="[63:0] A:R:G:B 16:16:16:16 little endian"/>
++      <entry name="abgr16161616" value="0x38344241" summary="[63:0] A:B:G:R 16:16:16:16 little endian"/>
++    </enum>
++
++    <request name="create_pool">
++      <description summary="create a shm pool">
++      Create a new wl_shm_pool object.
++
++      The pool can be used to create shared memory based buffer
++      objects.  The server will mmap size bytes of the passed file
++      descriptor, to use as backing memory for the pool.
++      </description>
++      <arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
++      <arg name="fd" type="fd" summary="file descriptor for the pool"/>
++      <arg name="size" type="int" summary="pool size, in bytes"/>
++    </request>
++
++    <event name="format">
++      <description summary="pixel format description">
++      Informs the client about a valid pixel format that
++      can be used for buffers. Known formats include
++      argb8888 and xrgb8888.
++      </description>
++      <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
++    </event>
++  </interface>
++
++  <interface name="wl_buffer" version="1">
++    <description summary="content for a wl_surface">
++      A buffer provides the content for a wl_surface. Buffers are
++      created through factory interfaces such as wl_shm, wp_linux_buffer_params
++      (from the linux-dmabuf protocol extension) or similar. It has a width and
++      a height and can be attached to a wl_surface, but the mechanism by which a
++      client provides and updates the contents is defined by the buffer factory
++      interface.
++
++      If the buffer uses a format that has an alpha channel, the alpha channel
++      is assumed to be premultiplied in the color channels unless otherwise
++      specified.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy a buffer">
++      Destroy a buffer. If and how you need to release the backing
++      storage is defined by the buffer factory interface.
++
++      For possible side-effects to a surface, see wl_surface.attach.
++      </description>
++    </request>
++
++    <event name="release">
++      <description summary="compositor releases buffer">
++      Sent when this wl_buffer is no longer used by the compositor.
++      The client is now free to reuse or destroy this buffer and its
++      backing storage.
++
++      If a client receives a release event before the frame callback
++      requested in the same wl_surface.commit that attaches this
++      wl_buffer to a surface, then the client is immediately free to
++      reuse the buffer and its backing storage, and does not need a
++      second buffer for the next surface content update. Typically
++      this is possible, when the compositor maintains a copy of the
++      wl_surface contents, e.g. as a GL texture. This is an important
++      optimization for GL(ES) compositors with wl_shm clients.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="wl_data_offer" version="3">
++    <description summary="offer to transfer data">
++      A wl_data_offer represents a piece of data offered for transfer
++      by another client (the source client).  It is used by the
++      copy-and-paste and drag-and-drop mechanisms.  The offer
++      describes the different mime types that the data can be
++      converted to and provides the mechanism for transferring the
++      data directly from the source client.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_finish" value="0"
++           summary="finish request was called untimely"/>
++      <entry name="invalid_action_mask" value="1"
++           summary="action mask contains invalid values"/>
++      <entry name="invalid_action" value="2"
++           summary="action argument has an invalid value"/>
++      <entry name="invalid_offer" value="3"
++           summary="offer doesn't accept this request"/>
++    </enum>
++
++    <request name="accept">
++      <description summary="accept one of the offered mime types">
++      Indicate that the client can accept the given mime type, or
++      NULL for not accepted.
++
++      For objects of version 2 or older, this request is used by the
++      client to give feedback whether the client can receive the given
++      mime type, or NULL if none is accepted; the feedback does not
++      determine whether the drag-and-drop operation succeeds or not.
++
++      For objects of version 3 or newer, this request determines the
++      final result of the drag-and-drop operation. If the end result
++      is that no mime types were accepted, the drag-and-drop operation
++      will be cancelled and the corresponding drag source will receive
++      wl_data_source.cancelled. Clients may still use this event in
++      conjunction with wl_data_source.action for feedback.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the accept request"/>
++      <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the client"/>
++    </request>
++
++    <request name="receive">
++      <description summary="request that the data is transferred">
++      To transfer the offered data, the client issues this request
++      and indicates the mime type it wants to receive.  The transfer
++      happens through the passed file descriptor (typically created
++      with the pipe system call).  The source client writes the data
++      in the mime type representation requested and then closes the
++      file descriptor.
++
++      The receiving client reads from the read end of the pipe until
++      EOF and then closes its end, at which point the transfer is
++      complete.
++
++      This request may happen multiple times for different mime types,
++      both before and after wl_data_device.drop. Drag-and-drop destination
++      clients may preemptively fetch data or examine it more closely to
++      determine acceptance.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type desired by receiver"/>
++      <arg name="fd" type="fd" summary="file descriptor for data transfer"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy data offer">
++      Destroy the data offer.
++      </description>
++    </request>
++
++    <event name="offer">
++      <description summary="advertise offered mime type">
++      Sent immediately after creating the wl_data_offer object.  One
++      event per offered mime type.
++      </description>
++      <arg name="mime_type" type="string" summary="offered mime type"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="finish" since="3">
++      <description summary="the offer will no longer be used">
++      Notifies the compositor that the drag destination successfully
++      finished the drag-and-drop operation.
++
++      Upon receiving this request, the compositor will emit
++      wl_data_source.dnd_finished on the drag source client.
++
++      It is a client error to perform other requests than
++      wl_data_offer.destroy after this one. It is also an error to perform
++      this request after a NULL mime type has been set in
++      wl_data_offer.accept or no action was received through
++      wl_data_offer.action.
++
++      If wl_data_offer.finish request is received for a non drag and drop
++      operation, the invalid_finish protocol error is raised.
++      </description>
++    </request>
++
++    <request name="set_actions" since="3">
++      <description summary="set the available/preferred drag-and-drop actions">
++      Sets the actions that the destination side client supports for
++      this operation. This request may trigger the emission of
++      wl_data_source.action and wl_data_offer.action events if the compositor
++      needs to change the selected action.
++
++      This request can be called multiple times throughout the
++      drag-and-drop operation, typically in response to wl_data_device.enter
++      or wl_data_device.motion events.
++
++      This request determines the final result of the drag-and-drop
++      operation. If the end result is that no action is accepted,
++      the drag source will receive wl_data_source.cancelled.
++
++      The dnd_actions argument must contain only values expressed in the
++      wl_data_device_manager.dnd_actions enum, and the preferred_action
++      argument must only contain one of those values set, otherwise it
++      will result in a protocol error.
++
++      While managing an "ask" action, the destination drag-and-drop client
++      may perform further wl_data_offer.receive requests, and is expected
++      to perform one last wl_data_offer.set_actions request with a preferred
++      action other than "ask" (and optionally wl_data_offer.accept) before
++      requesting wl_data_offer.finish, in order to convey the action selected
++      by the user. If the preferred action is not in the
++      wl_data_offer.source_actions mask, an error will be raised.
++
++      If the "ask" action is dismissed (e.g. user cancellation), the client
++      is expected to perform wl_data_offer.destroy right away.
++
++      This request can only be made on drag-and-drop offers, a protocol error
++      will be raised otherwise.
++      </description>
++      <arg name="dnd_actions" type="uint" summary="actions supported by the destination client"
++         enum="wl_data_device_manager.dnd_action"/>
++      <arg name="preferred_action" type="uint" summary="action preferred by the destination client"
++         enum="wl_data_device_manager.dnd_action"/>
++    </request>
++
++    <event name="source_actions" since="3">
++      <description summary="notify the source-side available actions">
++      This event indicates the actions offered by the data source. It
++      will be sent right after wl_data_device.enter, or anytime the source
++      side changes its offered actions through wl_data_source.set_actions.
++      </description>
++      <arg name="source_actions" type="uint" summary="actions offered by the data source"
++         enum="wl_data_device_manager.dnd_action"/>
++    </event>
++
++    <event name="action" since="3">
++      <description summary="notify the selected action">
++      This event indicates the action selected by the compositor after
++      matching the source/destination side actions. Only one action (or
++      none) will be offered here.
++
++      This event can be emitted multiple times during the drag-and-drop
++      operation in response to destination side action changes through
++      wl_data_offer.set_actions.
++
++      This event will no longer be emitted after wl_data_device.drop
++      happened on the drag-and-drop destination, the client must
++      honor the last action received, or the last preferred one set
++      through wl_data_offer.set_actions when handling an "ask" action.
++
++      Compositors may also change the selected action on the fly, mainly
++      in response to keyboard modifier changes during the drag-and-drop
++      operation.
++
++      The most recent action received is always the valid one. Prior to
++      receiving wl_data_device.drop, the chosen action may change (e.g.
++      due to keyboard modifiers being pressed). At the time of receiving
++      wl_data_device.drop the drag-and-drop destination must honor the
++      last action received.
++
++      Action changes may still happen after wl_data_device.drop,
++      especially on "ask" actions, where the drag-and-drop destination
++      may choose another action afterwards. Action changes happening
++      at this stage are always the result of inter-client negotiation, the
++      compositor shall no longer be able to induce a different action.
++
++      Upon "ask" actions, it is expected that the drag-and-drop destination
++      may potentially choose a different action and/or mime type,
++      based on wl_data_offer.source_actions and finally chosen by the
++      user (e.g. popping up a menu with the available options). The
++      final wl_data_offer.set_actions and wl_data_offer.accept requests
++      must happen before the call to wl_data_offer.finish.
++      </description>
++      <arg name="dnd_action" type="uint" summary="action selected by the compositor"
++         enum="wl_data_device_manager.dnd_action"/>
++    </event>
++  </interface>
++
++  <interface name="wl_data_source" version="3">
++    <description summary="offer to transfer data">
++      The wl_data_source object is the source side of a wl_data_offer.
++      It is created by the source client in a data transfer and
++      provides a way to describe the offered data and a way to respond
++      to requests to transfer the data.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_action_mask" value="0"
++           summary="action mask contains invalid values"/>
++      <entry name="invalid_source" value="1"
++           summary="source doesn't accept this request"/>
++    </enum>
++
++    <request name="offer">
++      <description summary="add an offered mime type">
++      This request adds a mime type to the set of mime types
++      advertised to targets.  Can be called several times to offer
++      multiple types.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type offered by the data source"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the data source">
++      Destroy the data source.
++      </description>
++    </request>
++
++    <event name="target">
++      <description summary="a target accepts an offered mime type">
++      Sent when a target accepts pointer_focus or motion events.  If
++      a target does not accept any of the offered types, type is NULL.
++
++      Used for feedback during drag-and-drop.
++      </description>
++      <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the target"/>
++    </event>
++
++    <event name="send">
++      <description summary="send the data">
++      Request for data from the client.  Send the data as the
++      specified mime type over the passed file descriptor, then
++      close it.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type for the data"/>
++      <arg name="fd" type="fd" summary="file descriptor for the data"/>
++    </event>
++
++    <event name="cancelled">
++      <description summary="selection was cancelled">
++      This data source is no longer valid. There are several reasons why
++      this could happen:
++
++      - The data source has been replaced by another data source.
++      - The drag-and-drop operation was performed, but the drop destination
++        did not accept any of the mime types offered through
++        wl_data_source.target.
++      - The drag-and-drop operation was performed, but the drop destination
++        did not select any of the actions present in the mask offered through
++        wl_data_source.action.
++      - The drag-and-drop operation was performed but didn't happen over a
++        surface.
++      - The compositor cancelled the drag-and-drop operation (e.g. compositor
++        dependent timeouts to avoid stale drag-and-drop transfers).
++
++      The client should clean up and destroy this data source.
++
++      For objects of version 2 or older, wl_data_source.cancelled will
++      only be emitted if the data source was replaced by another data
++      source.
++      </description>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="set_actions" since="3">
++      <description summary="set the available drag-and-drop actions">
++      Sets the actions that the source side client supports for this
++      operation. This request may trigger wl_data_source.action and
++      wl_data_offer.action events if the compositor needs to change the
++      selected action.
++
++      The dnd_actions argument must contain only values expressed in the
++      wl_data_device_manager.dnd_actions enum, otherwise it will result
++      in a protocol error.
++
++      This request must be made once only, and can only be made on sources
++      used in drag-and-drop, so it must be performed before
++      wl_data_device.start_drag. Attempting to use the source other than
++      for drag-and-drop will raise a protocol error.
++      </description>
++      <arg name="dnd_actions" type="uint" summary="actions supported by the data source"
++         enum="wl_data_device_manager.dnd_action"/>
++    </request>
++
++    <event name="dnd_drop_performed" since="3">
++      <description summary="the drag-and-drop operation physically finished">
++      The user performed the drop action. This event does not indicate
++      acceptance, wl_data_source.cancelled may still be emitted afterwards
++      if the drop destination does not accept any mime type.
++
++      However, this event might however not be received if the compositor
++      cancelled the drag-and-drop operation before this event could happen.
++
++      Note that the data_source may still be used in the future and should
++      not be destroyed here.
++      </description>
++    </event>
++
++    <event name="dnd_finished" since="3">
++      <description summary="the drag-and-drop operation concluded">
++      The drop destination finished interoperating with this data
++      source, so the client is now free to destroy this data source and
++      free all associated data.
++
++      If the action used to perform the operation was "move", the
++      source can now delete the transferred data.
++      </description>
++    </event>
++
++    <event name="action" since="3">
++      <description summary="notify the selected action">
++      This event indicates the action selected by the compositor after
++      matching the source/destination side actions. Only one action (or
++      none) will be offered here.
++
++      This event can be emitted multiple times during the drag-and-drop
++      operation, mainly in response to destination side changes through
++      wl_data_offer.set_actions, and as the data device enters/leaves
++      surfaces.
++
++      It is only possible to receive this event after
++      wl_data_source.dnd_drop_performed if the drag-and-drop operation
++      ended in an "ask" action, in which case the final wl_data_source.action
++      event will happen immediately before wl_data_source.dnd_finished.
++
++      Compositors may also change the selected action on the fly, mainly
++      in response to keyboard modifier changes during the drag-and-drop
++      operation.
++
++      The most recent action received is always the valid one. The chosen
++      action may change alongside negotiation (e.g. an "ask" action can turn
++      into a "move" operation), so the effects of the final action must
++      always be applied in wl_data_offer.dnd_finished.
++
++      Clients can trigger cursor surface changes from this point, so
++      they reflect the current action.
++      </description>
++      <arg name="dnd_action" type="uint" summary="action selected by the compositor"
++         enum="wl_data_device_manager.dnd_action"/>
++    </event>
++  </interface>
++
++  <interface name="wl_data_device" version="3">
++    <description summary="data transfer device">
++      There is one wl_data_device per seat which can be obtained
++      from the global wl_data_device_manager singleton.
++
++      A wl_data_device provides access to inter-client data transfer
++      mechanisms such as copy-and-paste and drag-and-drop.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="start_drag">
++      <description summary="start drag-and-drop operation">
++      This request asks the compositor to start a drag-and-drop
++      operation on behalf of the client.
++
++      The source argument is the data source that provides the data
++      for the eventual data transfer. If source is NULL, enter, leave
++      and motion events are sent only to the client that initiated the
++      drag and the client is expected to handle the data passing
++      internally. If source is destroyed, the drag-and-drop session will be
++      cancelled.
++
++      The origin surface is the surface where the drag originates and
++      the client must have an active implicit grab that matches the
++      serial.
++
++      The icon surface is an optional (can be NULL) surface that
++      provides an icon to be moved around with the cursor.  Initially,
++      the top-left corner of the icon surface is placed at the cursor
++      hotspot, but subsequent wl_surface.attach request can move the
++      relative position. Attach requests must be confirmed with
++      wl_surface.commit as usual. The icon surface is given the role of
++      a drag-and-drop icon. If the icon surface already has another role,
++      it raises a protocol error.
++
++      The current and pending input regions of the icon wl_surface are
++      cleared, and wl_surface.set_input_region is ignored until the
++      wl_surface is no longer used as the icon surface. When the use
++      as an icon ends, the current and pending input regions become
++      undefined, and the wl_surface is unmapped.
++      </description>
++      <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
++      <arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
++      <arg name="icon" type="object" interface="wl_surface" allow-null="true" summary="drag-and-drop icon surface"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the origin"/>
++    </request>
++
++    <request name="set_selection">
++      <description summary="copy data to the selection">
++      This request asks the compositor to set the selection
++      to the data from the source on behalf of the client.
++
++      To unset the selection, set the source to NULL.
++      </description>
++      <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
++      <arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
++    </request>
++
++    <event name="data_offer">
++      <description summary="introduce a new wl_data_offer">
++      The data_offer event introduces a new wl_data_offer object,
++      which will subsequently be used in either the
++      data_device.enter event (for drag-and-drop) or the
++      data_device.selection event (for selections).  Immediately
++      following the data_device.data_offer event, the new data_offer
++      object will send out data_offer.offer events to describe the
++      mime types it offers.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_offer" summary="the new data_offer object"/>
++    </event>
++
++    <event name="enter">
++      <description summary="initiate drag-and-drop session">
++      This event is sent when an active drag-and-drop pointer enters
++      a surface owned by the client.  The position of the pointer at
++      enter time is provided by the x and y arguments, in surface-local
++      coordinates.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="client surface entered"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++      <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++         summary="source data_offer object"/>
++    </event>
++
++    <event name="leave">
++      <description summary="end drag-and-drop session">
++      This event is sent when the drag-and-drop pointer leaves the
++      surface and the session ends.  The client must destroy the
++      wl_data_offer introduced at enter time at this point.
++      </description>
++    </event>
++
++    <event name="motion">
++      <description summary="drag-and-drop session motion">
++      This event is sent when the drag-and-drop pointer moves within
++      the currently focused surface. The new position of the pointer
++      is provided by the x and y arguments, in surface-local
++      coordinates.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="drop">
++      <description summary="end drag-and-drop session successfully">
++      The event is sent when a drag-and-drop operation is ended
++      because the implicit grab is removed.
++
++      The drag-and-drop destination is expected to honor the last action
++      received through wl_data_offer.action, if the resulting action is
++      "copy" or "move", the destination can still perform
++      wl_data_offer.receive requests, and is expected to end all
++      transfers with a wl_data_offer.finish request.
++
++      If the resulting action is "ask", the action will not be considered
++      final. The drag-and-drop destination is expected to perform one last
++      wl_data_offer.set_actions request, or wl_data_offer.destroy in order
++      to cancel the operation.
++      </description>
++    </event>
++
++    <event name="selection">
++      <description summary="advertise new selection">
++      The selection event is sent out to notify the client of a new
++      wl_data_offer for the selection for this device.  The
++      data_device.data_offer and the data_offer.offer events are
++      sent out immediately before this event to introduce the data
++      offer object.  The selection event is sent to a client
++      immediately before receiving keyboard focus and when a new
++      selection is set while the client has keyboard focus.  The
++      data_offer is valid until a new data_offer or NULL is received
++      or until the client loses keyboard focus.  Switching surface with
++      keyboard focus within the same client doesn't mean a new selection
++      will be sent.  The client must destroy the previous selection
++      data_offer, if any, upon receiving this event.
++      </description>
++      <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++         summary="selection data_offer object"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <request name="release" type="destructor" since="2">
++      <description summary="destroy data device">
++      This request destroys the data device.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="wl_data_device_manager" version="3">
++    <description summary="data transfer interface">
++      The wl_data_device_manager is a singleton global object that
++      provides access to inter-client data transfer mechanisms such as
++      copy-and-paste and drag-and-drop.  These mechanisms are tied to
++      a wl_seat and this interface lets a client get a wl_data_device
++      corresponding to a wl_seat.
++
++      Depending on the version bound, the objects created from the bound
++      wl_data_device_manager object will have different requirements for
++      functioning properly. See wl_data_source.set_actions,
++      wl_data_offer.accept and wl_data_offer.finish for details.
++    </description>
++
++    <request name="create_data_source">
++      <description summary="create a new data source">
++      Create a new data source.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_source" summary="data source to create"/>
++    </request>
++
++    <request name="get_data_device">
++      <description summary="create a new data device">
++      Create a new data device for a given seat.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_device" summary="data device to create"/>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat associated with the data device"/>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <enum name="dnd_action" bitfield="true" since="3">
++      <description summary="drag and drop actions">
++      This is a bitmask of the available/preferred actions in a
++      drag-and-drop operation.
++
++      In the compositor, the selected action is a result of matching the
++      actions offered by the source and destination sides.  "action" events
++      with a "none" action will be sent to both source and destination if
++      there is no match. All further checks will effectively happen on
++      (source actions ∩ destination actions).
++
++      In addition, compositors may also pick different actions in
++      reaction to key modifiers being pressed. One common design that
++      is used in major toolkits (and the behavior recommended for
++      compositors) is:
++
++      - If no modifiers are pressed, the first match (in bit order)
++        will be used.
++      - Pressing Shift selects "move", if enabled in the mask.
++      - Pressing Control selects "copy", if enabled in the mask.
++
++      Behavior beyond that is considered implementation-dependent.
++      Compositors may for example bind other modifiers (like Alt/Meta)
++      or drags initiated with other buttons than BTN_LEFT to specific
++      actions (e.g. "ask").
++      </description>
++      <entry name="none" value="0" summary="no action"/>
++      <entry name="copy" value="1" summary="copy action"/>
++      <entry name="move" value="2" summary="move action"/>
++      <entry name="ask" value="4" summary="ask action"/>
++    </enum>
++  </interface>
++
++  <interface name="wl_shell" version="1">
++    <description summary="create desktop-style surfaces">
++      This interface is implemented by servers that provide
++      desktop-style user interfaces.
++
++      It allows clients to associate a wl_shell_surface with
++      a basic surface.
++
++      Note! This protocol is deprecated and not intended for production use.
++      For desktop-style user interfaces, use xdg_shell. Compositors and clients
++      should not implement this interface.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="get_shell_surface">
++      <description summary="create a shell surface from a surface">
++      Create a shell surface for an existing surface. This gives
++      the wl_surface the role of a shell surface. If the wl_surface
++      already has another role, it raises a protocol error.
++
++      Only one shell surface can be associated with a given surface.
++      </description>
++      <arg name="id" type="new_id" interface="wl_shell_surface" summary="shell surface to create"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface to be given the shell surface role"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shell_surface" version="1">
++    <description summary="desktop-style metadata interface">
++      An interface that may be implemented by a wl_surface, for
++      implementations that provide a desktop-style user interface.
++
++      It provides requests to treat surfaces like toplevel, fullscreen
++      or popup windows, move, resize or maximize them, associate
++      metadata like title and class, etc.
++
++      On the server side the object is automatically destroyed when
++      the related wl_surface is destroyed. On the client side,
++      wl_shell_surface_destroy() must be called before destroying
++      the wl_surface object.
++    </description>
++
++    <request name="pong">
++      <description summary="respond to a ping event">
++      A client must respond to a ping event with a pong request or
++      the client may be deemed unresponsive.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the ping event"/>
++    </request>
++
++    <request name="move">
++      <description summary="start an interactive move">
++      Start a pointer-driven move of the surface.
++
++      This request must be used in response to a button press event.
++      The server may ignore move requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++    </request>
++
++    <enum name="resize" bitfield="true">
++      <description summary="edge values for resizing">
++      These values are used to indicate which edge of a surface
++      is being dragged in a resize operation. The server may
++      use this information to adapt its behavior, e.g. choose
++      an appropriate cursor image.
++      </description>
++      <entry name="none" value="0" summary="no edge"/>
++      <entry name="top" value="1" summary="top edge"/>
++      <entry name="bottom" value="2" summary="bottom edge"/>
++      <entry name="left" value="4" summary="left edge"/>
++      <entry name="top_left" value="5" summary="top and left edges"/>
++      <entry name="bottom_left" value="6" summary="bottom and left edges"/>
++      <entry name="right" value="8" summary="right edge"/>
++      <entry name="top_right" value="9" summary="top and right edges"/>
++      <entry name="bottom_right" value="10" summary="bottom and right edges"/>
++    </enum>
++
++    <request name="resize">
++      <description summary="start an interactive resize">
++      Start a pointer-driven resizing of the surface.
++
++      This request must be used in response to a button press event.
++      The server may ignore resize requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++      <arg name="edges" type="uint" enum="resize" summary="which edge or corner is being dragged"/>
++    </request>
++
++    <request name="set_toplevel">
++      <description summary="make the surface a toplevel surface">
++      Map the surface as a toplevel surface.
++
++      A toplevel surface is not fullscreen, maximized or transient.
++      </description>
++    </request>
++
++    <enum name="transient" bitfield="true">
++      <description summary="details of transient behaviour">
++      These flags specify details of the expected behaviour
++      of transient surfaces. Used in the set_transient request.
++      </description>
++      <entry name="inactive" value="0x1" summary="do not set keyboard focus"/>
++    </enum>
++
++    <request name="set_transient">
++      <description summary="make the surface a transient surface">
++      Map the surface relative to an existing surface.
++
++      The x and y arguments specify the location of the upper left
++      corner of the surface relative to the upper left corner of the
++      parent surface, in surface-local coordinates.
++
++      The flags argument controls details of the transient behaviour.
++      </description>
++      <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++    </request>
++
++    <enum name="fullscreen_method">
++      <description summary="different method to set the surface fullscreen">
++      Hints to indicate to the compositor how to deal with a conflict
++      between the dimensions of the surface and the dimensions of the
++      output. The compositor is free to ignore this parameter.
++      </description>
++      <entry name="default" value="0" summary="no preference, apply default policy"/>
++      <entry name="scale" value="1" summary="scale, preserve the surface's aspect ratio and center on output"/>
++      <entry name="driver" value="2" summary="switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch"/>
++      <entry name="fill" value="3" summary="no upscaling, center on output and add black borders to compensate size mismatch"/>
++    </enum>
++
++    <request name="set_fullscreen">
++      <description summary="make the surface a fullscreen surface">
++      Map the surface as a fullscreen surface.
++
++      If an output parameter is given then the surface will be made
++      fullscreen on that output. If the client does not specify the
++      output then the compositor will apply its policy - usually
++      choosing the output on which the surface has the biggest surface
++      area.
++
++      The client may specify a method to resolve a size conflict
++      between the output size and the surface size - this is provided
++      through the method parameter.
++
++      The framerate parameter is used only when the method is set
++      to "driver", to indicate the preferred framerate. A value of 0
++      indicates that the client does not care about framerate.  The
++      framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++
++      A method of "scale" or "driver" implies a scaling operation of
++      the surface, either via a direct scaling operation or a change of
++      the output mode. This will override any kind of output scaling, so
++      that mapping a surface with a buffer size equal to the mode can
++      fill the screen independent of buffer_scale.
++
++      A method of "fill" means we don't scale up the buffer, however
++      any output scale is applied. This means that you may run into
++      an edge case where the application maps a buffer with the same
++      size of the output mode but buffer_scale 1 (thus making a
++      surface larger than the output). In this case it is allowed to
++      downscale the results to fit the screen.
++
++      The compositor must reply to this request with a configure event
++      with the dimensions for the output on which the surface will
++      be made fullscreen.
++      </description>
++      <arg name="method" type="uint" enum="fullscreen_method" summary="method for resolving size conflict"/>
++      <arg name="framerate" type="uint" summary="framerate in mHz"/>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"
++         summary="output on which the surface is to be fullscreen"/>
++    </request>
++
++    <request name="set_popup">
++      <description summary="make the surface a popup surface">
++      Map the surface as a popup.
++
++      A popup surface is a transient surface with an added pointer
++      grab.
++
++      An existing implicit grab will be changed to owner-events mode,
++      and the popup grab will continue after the implicit grab ends
++      (i.e. releasing the mouse button does not cause the popup to
++      be unmapped).
++
++      The popup grab continues until the window is destroyed or a
++      mouse button is pressed in any other client's window. A click
++      in any of the client's surfaces is reported as normal, however,
++      clicks in other clients' surfaces will be discarded and trigger
++      the callback.
++
++      The x and y arguments specify the location of the upper left
++      corner of the surface relative to the upper left corner of the
++      parent surface, in surface-local coordinates.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++      <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++    </request>
++
++    <request name="set_maximized">
++      <description summary="make the surface a maximized surface">
++      Map the surface as a maximized surface.
++
++      If an output parameter is given then the surface will be
++      maximized on that output. If the client does not specify the
++      output then the compositor will apply its policy - usually
++      choosing the output on which the surface has the biggest surface
++      area.
++
++      The compositor will reply with a configure event telling
++      the expected new surface size. The operation is completed
++      on the next buffer attach to this surface.
++
++      A maximized surface typically fills the entire output it is
++      bound to, except for desktop elements such as panels. This is
++      the main difference between a maximized shell surface and a
++      fullscreen shell surface.
++
++      The details depend on the compositor implementation.
++      </description>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"
++         summary="output on which the surface is to be maximized"/>
++    </request>
++
++    <request name="set_title">
++      <description summary="set surface title">
++      Set a short title for the surface.
++
++      This string may be used to identify the surface in a task bar,
++      window list, or other user interface elements provided by the
++      compositor.
++
++      The string must be encoded in UTF-8.
++      </description>
++      <arg name="title" type="string" summary="surface title"/>
++    </request>
++
++    <request name="set_class">
++      <description summary="set surface class">
++      Set a class for the surface.
++
++      The surface class identifies the general class of applications
++      to which the surface belongs. A common convention is to use the
++      file name (or the full path if it is a non-standard location) of
++      the application's .desktop file as the class.
++      </description>
++      <arg name="class_" type="string" summary="surface class"/>
++    </request>
++
++    <event name="ping">
++      <description summary="ping client">
++      Ping a client to check if it is receiving events and sending
++      requests. A client is expected to reply with a pong request.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the ping"/>
++    </event>
++
++    <event name="configure">
++      <description summary="suggest resize">
++      The configure event asks the client to resize its surface.
++
++      The size is a hint, in the sense that the client is free to
++      ignore it if it doesn't resize, pick a smaller size (to
++      satisfy aspect ratio or resize in steps of NxM pixels).
++
++      The edges parameter provides a hint about how the surface
++      was resized. The client may use this information to decide
++      how to adjust its content to the new size (e.g. a scrolling
++      area might adjust its content position to leave the viewable
++      content unmoved).
++
++      The client is free to dismiss all but the last configure
++      event it received.
++
++      The width and height arguments specify the size of the window
++      in surface-local coordinates.
++      </description>
++      <arg name="edges" type="uint" enum="resize" summary="how the surface was resized"/>
++      <arg name="width" type="int" summary="new width of the surface"/>
++      <arg name="height" type="int" summary="new height of the surface"/>
++    </event>
++
++    <event name="popup_done">
++      <description summary="popup interaction is done">
++      The popup_done event is sent out when a popup grab is broken,
++      that is, when the user clicks a surface that doesn't belong
++      to the client owning the popup surface.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="wl_surface" version="5">
++    <description summary="an onscreen surface">
++      A surface is a rectangular area that may be displayed on zero
++      or more outputs, and shown any number of times at the compositor's
++      discretion. They can present wl_buffers, receive user input, and
++      define a local coordinate system.
++
++      The size of a surface (and relative positions on it) is described
++      in surface-local coordinates, which may differ from the buffer
++      coordinates of the pixel content, in case a buffer_transform
++      or a buffer_scale is used.
++
++      A surface without a "role" is fairly useless: a compositor does
++      not know where, when or how to present it. The role is the
++      purpose of a wl_surface. Examples of roles are a cursor for a
++      pointer (as set by wl_pointer.set_cursor), a drag icon
++      (wl_data_device.start_drag), a sub-surface
++      (wl_subcompositor.get_subsurface), and a window as defined by a
++      shell protocol (e.g. wl_shell.get_shell_surface).
++
++      A surface can have only one role at a time. Initially a
++      wl_surface does not have a role. Once a wl_surface is given a
++      role, it is set permanently for the whole lifetime of the
++      wl_surface object. Giving the current role again is allowed,
++      unless explicitly forbidden by the relevant interface
++      specification.
++
++      Surface roles are given by requests in other interfaces such as
++      wl_pointer.set_cursor. The request should explicitly mention
++      that this request gives a role to a wl_surface. Often, this
++      request also creates a new protocol object that represents the
++      role and adds additional functionality to wl_surface. When a
++      client wants to destroy a wl_surface, they must destroy this 'role
++      object' before the wl_surface.
++
++      Destroying the role object does not remove the role from the
++      wl_surface, but it may stop the wl_surface from "playing the role".
++      For instance, if a wl_subsurface object is destroyed, the wl_surface
++      it was created for will be unmapped and forget its position and
++      z-order. It is allowed to create a wl_subsurface for the same
++      wl_surface again, but it is not allowed to use the wl_surface as
++      a cursor (cursor is a different role than sub-surface, and role
++      switching is not allowed).
++    </description>
++
++    <enum name="error">
++      <description summary="wl_surface error values">
++      These errors can be emitted in response to wl_surface requests.
++      </description>
++      <entry name="invalid_scale" value="0" summary="buffer scale value is invalid"/>
++      <entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
++      <entry name="invalid_size" value="2" summary="buffer size is invalid"/>
++      <entry name="invalid_offset" value="3" summary="buffer offset is invalid"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="delete surface">
++      Deletes the surface and invalidates its object ID.
++      </description>
++    </request>
++
++    <request name="attach">
++      <description summary="set the surface contents">
++      Set a buffer as the content of this surface.
++
++      The new size of the surface is calculated based on the buffer
++      size transformed by the inverse buffer_transform and the
++      inverse buffer_scale. This means that at commit time the supplied
++      buffer size must be an integer multiple of the buffer_scale. If
++      that's not the case, an invalid_size error is sent.
++
++      The x and y arguments specify the location of the new pending
++      buffer's upper left corner, relative to the current buffer's upper
++      left corner, in surface-local coordinates. In other words, the
++      x and y, combined with the new surface size define in which
++      directions the surface's size changes. Setting anything other than 0
++      as x and y arguments is discouraged, and should instead be replaced
++      with using the separate wl_surface.offset request.
++
++      When the bound wl_surface version is 5 or higher, passing any
++      non-zero x or y is a protocol violation, and will result in an
++      'invalid_offset' error being raised. To achieve equivalent semantics,
++      use wl_surface.offset.
++
++      Surface contents are double-buffered state, see wl_surface.commit.
++
++      The initial surface contents are void; there is no content.
++      wl_surface.attach assigns the given wl_buffer as the pending
++      wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++      surface contents, and the size of the surface becomes the size
++      calculated from the wl_buffer, as described above. After commit,
++      there is no pending buffer until the next attach.
++
++      Committing a pending wl_buffer allows the compositor to read the
++      pixels in the wl_buffer. The compositor may access the pixels at
++      any time after the wl_surface.commit request. When the compositor
++      will not access the pixels anymore, it will send the
++      wl_buffer.release event. Only after receiving wl_buffer.release,
++      the client may reuse the wl_buffer. A wl_buffer that has been
++      attached and then replaced by another attach instead of committed
++      will not receive a release event, and is not used by the
++      compositor.
++
++      If a pending wl_buffer has been committed to more than one wl_surface,
++      the delivery of wl_buffer.release events becomes undefined. A well
++      behaved client should not rely on wl_buffer.release events in this
++      case. Alternatively, a client could create multiple wl_buffer objects
++      from the same backing storage or use wp_linux_buffer_release.
++
++      Destroying the wl_buffer after wl_buffer.release does not change
++      the surface contents. Destroying the wl_buffer before wl_buffer.release
++      is allowed as long as the underlying buffer storage isn't re-used (this
++      can happen e.g. on client process termination). However, if the client
++      destroys the wl_buffer before receiving the wl_buffer.release event and
++      mutates the underlying buffer storage, the surface contents become
++      undefined immediately.
++
++      If wl_surface.attach is sent with a NULL wl_buffer, the
++      following wl_surface.commit will remove the surface content.
++      </description>
++      <arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
++         summary="buffer of surface contents"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <request name="damage">
++      <description summary="mark part of the surface damaged">
++      This request is used to describe the regions where the pending
++      buffer is different from the current surface contents, and where
++      the surface therefore needs to be repainted. The compositor
++      ignores the parts of the damage that fall outside of the surface.
++
++      Damage is double-buffered state, see wl_surface.commit.
++
++      The damage rectangle is specified in surface-local coordinates,
++      where x and y specify the upper left corner of the damage rectangle.
++
++      The initial value for pending damage is empty: no damage.
++      wl_surface.damage adds pending damage: the new pending damage
++      is the union of old pending damage and the given rectangle.
++
++      wl_surface.commit assigns pending damage as the current damage,
++      and clears pending damage. The server will clear the current
++      damage as it repaints the surface.
++
++      Note! New clients should not use this request. Instead damage can be
++      posted with wl_surface.damage_buffer which uses buffer coordinates
++      instead of surface coordinates.
++      </description>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="width" type="int" summary="width of damage rectangle"/>
++      <arg name="height" type="int" summary="height of damage rectangle"/>
++    </request>
++
++    <request name="frame">
++      <description summary="request a frame throttling hint">
++      Request a notification when it is a good time to start drawing a new
++      frame, by creating a frame callback. This is useful for throttling
++      redrawing operations, and driving animations.
++
++      When a client is animating on a wl_surface, it can use the 'frame'
++      request to get notified when it is a good time to draw and commit the
++      next frame of animation. If the client commits an update earlier than
++      that, it is likely that some updates will not make it to the display,
++      and the client is wasting resources by drawing too often.
++
++      The frame request will take effect on the next wl_surface.commit.
++      The notification will only be posted for one frame unless
++      requested again. For a wl_surface, the notifications are posted in
++      the order the frame requests were committed.
++
++      The server must send the notifications so that a client
++      will not send excessive updates, while still allowing
++      the highest possible update rate for clients that wait for the reply
++      before drawing again. The server should give some time for the client
++      to draw and commit after sending the frame callback events to let it
++      hit the next output refresh.
++
++      A server should avoid signaling the frame callbacks if the
++      surface is not visible in any way, e.g. the surface is off-screen,
++      or completely obscured by other opaque surfaces.
++
++      The object returned by this request will be destroyed by the
++      compositor after the callback is fired and as such the client must not
++      attempt to use it after that point.
++
++      The callback_data passed in the callback is the current time, in
++      milliseconds, with an undefined base.
++      </description>
++      <arg name="callback" type="new_id" interface="wl_callback" summary="callback object for the frame request"/>
++    </request>
++
++    <request name="set_opaque_region">
++      <description summary="set opaque region">
++      This request sets the region of the surface that contains
++      opaque content.
++
++      The opaque region is an optimization hint for the compositor
++      that lets it optimize the redrawing of content behind opaque
++      regions.  Setting an opaque region is not required for correct
++      behaviour, but marking transparent content as opaque will result
++      in repaint artifacts.
++
++      The opaque region is specified in surface-local coordinates.
++
++      The compositor ignores the parts of the opaque region that fall
++      outside of the surface.
++
++      Opaque region is double-buffered state, see wl_surface.commit.
++
++      wl_surface.set_opaque_region changes the pending opaque region.
++      wl_surface.commit copies the pending region to the current region.
++      Otherwise, the pending and current regions are never changed.
++
++      The initial value for an opaque region is empty. Setting the pending
++      opaque region has copy semantics, and the wl_region object can be
++      destroyed immediately. A NULL wl_region causes the pending opaque
++      region to be set to empty.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="opaque region of the surface"/>
++    </request>
++
++    <request name="set_input_region">
++      <description summary="set input region">
++      This request sets the region of the surface that can receive
++      pointer and touch events.
++
++      Input events happening outside of this region will try the next
++      surface in the server surface stack. The compositor ignores the
++      parts of the input region that fall outside of the surface.
++
++      The input region is specified in surface-local coordinates.
++
++      Input region is double-buffered state, see wl_surface.commit.
++
++      wl_surface.set_input_region changes the pending input region.
++      wl_surface.commit copies the pending region to the current region.
++      Otherwise the pending and current regions are never changed,
++      except cursor and icon surfaces are special cases, see
++      wl_pointer.set_cursor and wl_data_device.start_drag.
++
++      The initial value for an input region is infinite. That means the
++      whole surface will accept input. Setting the pending input region
++      has copy semantics, and the wl_region object can be destroyed
++      immediately. A NULL wl_region causes the input region to be set
++      to infinite.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="input region of the surface"/>
++    </request>
++
++    <request name="commit">
++      <description summary="commit pending surface state">
++      Surface state (input, opaque, and damage regions, attached buffers,
++      etc.) is double-buffered. Protocol requests modify the pending state,
++      as opposed to the current state in use by the compositor. A commit
++      request atomically applies all pending state, replacing the current
++      state. After commit, the new pending state is as documented for each
++      related request.
++
++      On commit, a pending wl_buffer is applied first, and all other state
++      second. This means that all coordinates in double-buffered state are
++      relative to the new wl_buffer coming into use, except for
++      wl_surface.attach itself. If there is no pending wl_buffer, the
++      coordinates are relative to the current surface contents.
++
++      All requests that need a commit to become effective are documented
++      to affect double-buffered state.
++
++      Other interfaces may add further double-buffered surface state.
++      </description>
++    </request>
++
++    <event name="enter">
++      <description summary="surface enters an output">
++      This is emitted whenever a surface's creation, movement, or resizing
++      results in some part of it being within the scanout region of an
++      output.
++
++      Note that a surface may be overlapping with zero or more outputs.
++      </description>
++      <arg name="output" type="object" interface="wl_output" summary="output entered by the surface"/>
++    </event>
++
++    <event name="leave">
++      <description summary="surface leaves an output">
++      This is emitted whenever a surface's creation, movement, or resizing
++      results in it no longer having any part of it within the scanout region
++      of an output.
++
++      Clients should not use the number of outputs the surface is on for frame
++      throttling purposes. The surface might be hidden even if no leave event
++      has been sent, and the compositor might expect new surface content
++      updates even if no enter event has been sent. The frame event should be
++      used instead.
++      </description>
++      <arg name="output" type="object" interface="wl_output" summary="output left by the surface"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <request name="set_buffer_transform" since="2">
++      <description summary="sets the buffer transformation">
++      This request sets an optional transformation on how the compositor
++      interprets the contents of the buffer attached to the surface. The
++      accepted values for the transform parameter are the values for
++      wl_output.transform.
++
++      Buffer transform is double-buffered state, see wl_surface.commit.
++
++      A newly created surface has its buffer transformation set to normal.
++
++      wl_surface.set_buffer_transform changes the pending buffer
++      transformation. wl_surface.commit copies the pending buffer
++      transformation to the current one. Otherwise, the pending and current
++      values are never changed.
++
++      The purpose of this request is to allow clients to render content
++      according to the output transform, thus permitting the compositor to
++      use certain optimizations even if the display is rotated. Using
++      hardware overlays and scanning out a client buffer for fullscreen
++      surfaces are examples of such optimizations. Those optimizations are
++      highly dependent on the compositor implementation, so the use of this
++      request should be considered on a case-by-case basis.
++
++      Note that if the transform value includes 90 or 270 degree rotation,
++      the width of the buffer will become the surface height and the height
++      of the buffer will become the surface width.
++
++      If transform is not one of the values from the
++      wl_output.transform enum the invalid_transform protocol error
++      is raised.
++      </description>
++      <arg name="transform" type="int" enum="wl_output.transform"
++         summary="transform for interpreting buffer contents"/>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <request name="set_buffer_scale" since="3">
++      <description summary="sets the buffer scaling factor">
++      This request sets an optional scaling factor on how the compositor
++      interprets the contents of the buffer attached to the window.
++
++      Buffer scale is double-buffered state, see wl_surface.commit.
++
++      A newly created surface has its buffer scale set to 1.
++
++      wl_surface.set_buffer_scale changes the pending buffer scale.
++      wl_surface.commit copies the pending buffer scale to the current one.
++      Otherwise, the pending and current values are never changed.
++
++      The purpose of this request is to allow clients to supply higher
++      resolution buffer data for use on high resolution outputs. It is
++      intended that you pick the same buffer scale as the scale of the
++      output that the surface is displayed on. This means the compositor
++      can avoid scaling when rendering the surface on that output.
++
++      Note that if the scale is larger than 1, then you have to attach
++      a buffer that is larger (by a factor of scale in each dimension)
++      than the desired surface size.
++
++      If scale is not positive the invalid_scale protocol error is
++      raised.
++      </description>
++      <arg name="scale" type="int"
++         summary="positive scale for interpreting buffer contents"/>
++    </request>
++
++    <!-- Version 4 additions -->
++    <request name="damage_buffer" since="4">
++      <description summary="mark part of the surface damaged using buffer coordinates">
++      This request is used to describe the regions where the pending
++      buffer is different from the current surface contents, and where
++      the surface therefore needs to be repainted. The compositor
++      ignores the parts of the damage that fall outside of the surface.
++
++      Damage is double-buffered state, see wl_surface.commit.
++
++      The damage rectangle is specified in buffer coordinates,
++      where x and y specify the upper left corner of the damage rectangle.
++
++      The initial value for pending damage is empty: no damage.
++      wl_surface.damage_buffer adds pending damage: the new pending
++      damage is the union of old pending damage and the given rectangle.
++
++      wl_surface.commit assigns pending damage as the current damage,
++      and clears pending damage. The server will clear the current
++      damage as it repaints the surface.
++
++      This request differs from wl_surface.damage in only one way - it
++      takes damage in buffer coordinates instead of surface-local
++      coordinates. While this generally is more intuitive than surface
++      coordinates, it is especially desirable when using wp_viewport
++      or when a drawing library (like EGL) is unaware of buffer scale
++      and buffer transform.
++
++      Note: Because buffer transformation changes and damage requests may
++      be interleaved in the protocol stream, it is impossible to determine
++      the actual mapping between surface and buffer damage until
++      wl_surface.commit time. Therefore, compositors wishing to take both
++      kinds of damage into account will have to accumulate damage from the
++      two requests separately and only transform from one to the other
++      after receiving the wl_surface.commit.
++      </description>
++      <arg name="x" type="int" summary="buffer-local x coordinate"/>
++      <arg name="y" type="int" summary="buffer-local y coordinate"/>
++      <arg name="width" type="int" summary="width of damage rectangle"/>
++      <arg name="height" type="int" summary="height of damage rectangle"/>
++    </request>
++
++    <!-- Version 5 additions -->
++
++    <request name="offset" since="5">
++      <description summary="set the surface contents offset">
++      The x and y arguments specify the location of the new pending
++      buffer's upper left corner, relative to the current buffer's upper
++      left corner, in surface-local coordinates. In other words, the
++      x and y, combined with the new surface size define in which
++      directions the surface's size changes.
++
++      Surface location offset is double-buffered state, see
++      wl_surface.commit.
++
++      This request is semantically equivalent to and the replaces the x and y
++      arguments in the wl_surface.attach request in wl_surface versions prior
++      to 5. See wl_surface.attach for details.
++      </description>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++    </request>
++   </interface>
++
++  <interface name="wl_seat" version="8">
++    <description summary="group of input devices">
++      A seat is a group of keyboards, pointer and touch devices. This
++      object is published as a global during start up, or when such a
++      device is hot plugged.  A seat typically has a pointer and
++      maintains a keyboard focus and a pointer focus.
++    </description>
++
++    <enum name="capability" bitfield="true">
++      <description summary="seat capability bitmask">
++      This is a bitmask of capabilities this seat has; if a member is
++      set, then it is present on the seat.
++      </description>
++      <entry name="pointer" value="1" summary="the seat has pointer devices"/>
++      <entry name="keyboard" value="2" summary="the seat has one or more keyboards"/>
++      <entry name="touch" value="4" summary="the seat has touch devices"/>
++    </enum>
++
++    <enum name="error">
++      <description summary="wl_seat error values">
++      These errors can be emitted in response to wl_seat requests.
++      </description>
++      <entry name="missing_capability" value="0"
++           summary="get_pointer, get_keyboard or get_touch called on seat without the matching capability"/>
++    </enum>
++
++    <event name="capabilities">
++      <description summary="seat capabilities changed">
++      This is emitted whenever a seat gains or loses the pointer,
++      keyboard or touch capabilities.  The argument is a capability
++      enum containing the complete set of capabilities this seat has.
++
++      When the pointer capability is added, a client may create a
++      wl_pointer object using the wl_seat.get_pointer request. This object
++      will receive pointer events until the capability is removed in the
++      future.
++
++      When the pointer capability is removed, a client should destroy the
++      wl_pointer objects associated with the seat where the capability was
++      removed, using the wl_pointer.release request. No further pointer
++      events will be received on these objects.
++
++      In some compositors, if a seat regains the pointer capability and a
++      client has a previously obtained wl_pointer object of version 4 or
++      less, that object may start sending pointer events again. This
++      behavior is considered a misinterpretation of the intended behavior
++      and must not be relied upon by the client. wl_pointer objects of
++      version 5 or later must not send events if created before the most
++      recent event notifying the client of an added pointer capability.
++
++      The above behavior also applies to wl_keyboard and wl_touch with the
++      keyboard and touch capabilities, respectively.
++      </description>
++      <arg name="capabilities" type="uint" enum="capability" summary="capabilities of the seat"/>
++    </event>
++
++    <request name="get_pointer">
++      <description summary="return pointer object">
++      The ID provided will be initialized to the wl_pointer interface
++      for this seat.
++
++      This request only takes effect if the seat has the pointer
++      capability, or has had the pointer capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the pointer capability. The missing_capability error will
++      be sent in this case.
++      </description>
++      <arg name="id" type="new_id" interface="wl_pointer" summary="seat pointer"/>
++    </request>
++
++    <request name="get_keyboard">
++      <description summary="return keyboard object">
++      The ID provided will be initialized to the wl_keyboard interface
++      for this seat.
++
++      This request only takes effect if the seat has the keyboard
++      capability, or has had the keyboard capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the keyboard capability. The missing_capability error will
++      be sent in this case.
++      </description>
++      <arg name="id" type="new_id" interface="wl_keyboard" summary="seat keyboard"/>
++    </request>
++
++    <request name="get_touch">
++      <description summary="return touch object">
++      The ID provided will be initialized to the wl_touch interface
++      for this seat.
++
++      This request only takes effect if the seat has the touch
++      capability, or has had the touch capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the touch capability. The missing_capability error will
++      be sent in this case.
++      </description>
++      <arg name="id" type="new_id" interface="wl_touch" summary="seat touch interface"/>
++    </request>
++
++    <!-- Version 2 additions -->
++
++    <event name="name" since="2">
++      <description summary="unique identifier for this seat">
++      In a multi-seat configuration the seat name can be used by clients to
++      help identify which physical devices the seat represents.
++
++      The seat name is a UTF-8 string with no convention defined for its
++      contents. Each name is unique among all wl_seat globals. The name is
++      only guaranteed to be unique for the current compositor instance.
++
++      The same seat names are used for all clients. Thus, the name can be
++      shared across processes to refer to a specific wl_seat global.
++
++      The name event is sent after binding to the seat global. This event is
++      only sent once per seat object, and the name does not change over the
++      lifetime of the wl_seat global.
++
++      Compositors may re-use the same seat name if the wl_seat global is
++      destroyed and re-created later.
++      </description>
++      <arg name="name" type="string" summary="seat identifier"/>
++    </event>
++
++    <!-- Version 5 additions -->
++
++    <request name="release" type="destructor" since="5">
++      <description summary="release the seat object">
++      Using this request a client can tell the server that it is not going to
++      use the seat object anymore.
++      </description>
++    </request>
++
++  </interface>
++
++  <interface name="wl_pointer" version="8">
++    <description summary="pointer input device">
++      The wl_pointer interface represents one or more input devices,
++      such as mice, which control the pointer location and pointer_focus
++      of a seat.
++
++      The wl_pointer interface generates motion, enter and leave
++      events for the surfaces that the pointer is located over,
++      and button and axis events for button presses, button releases
++      and scrolling.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="set_cursor">
++      <description summary="set the pointer surface">
++      Set the pointer surface, i.e., the surface that contains the
++      pointer image (cursor). This request gives the surface the role
++      of a cursor. If the surface already has another role, it raises
++      a protocol error.
++
++      The cursor actually changes only if the pointer
++      focus for this device is one of the requesting client's surfaces
++      or the surface parameter is the current pointer surface. If
++      there was a previous surface set with this request it is
++      replaced. If surface is NULL, the pointer image is hidden.
++
++      The parameters hotspot_x and hotspot_y define the position of
++      the pointer surface relative to the pointer location. Its
++      top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++      where (x, y) are the coordinates of the pointer location, in
++      surface-local coordinates.
++
++      On surface.attach requests to the pointer surface, hotspot_x
++      and hotspot_y are decremented by the x and y parameters
++      passed to the request. Attach must be confirmed by
++      wl_surface.commit as usual.
++
++      The hotspot can also be updated by passing the currently set
++      pointer surface to this request with new values for hotspot_x
++      and hotspot_y.
++
++      The current and pending input regions of the wl_surface are
++      cleared, and wl_surface.set_input_region is ignored until the
++      wl_surface is no longer used as the cursor. When the use as a
++      cursor ends, the current and pending input regions become
++      undefined, and the wl_surface is unmapped.
++
++      The serial parameter must match the latest wl_pointer.enter
++      serial number sent to the client. Otherwise the request will be
++      ignored.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" allow-null="true"
++         summary="pointer surface"/>
++      <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++      <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notification that this seat's pointer is focused on a certain
++      surface.
++
++      When a seat's focus enters a surface, the pointer image
++      is undefined and a client should respond to this event by setting
++      an appropriate pointer image with the set_cursor request.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface entered by the pointer"/>
++      <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notification that this seat's pointer is no longer focused on
++      a certain surface.
++
++      The leave notification is sent before the enter notification
++      for the new focus.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the leave event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface left by the pointer"/>
++    </event>
++
++    <event name="motion">
++      <description summary="pointer motion event">
++      Notification of pointer location change. The arguments
++      surface_x and surface_y are the location relative to the
++      focused surface.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <enum name="button_state">
++      <description summary="physical button state">
++      Describes the physical state of a button that produced the button
++      event.
++      </description>
++      <entry name="released" value="0" summary="the button is not pressed"/>
++      <entry name="pressed" value="1" summary="the button is pressed"/>
++    </enum>
++
++    <event name="button">
++      <description summary="pointer button event">
++      Mouse button click and release notifications.
++
++      The location of the click is given by the last motion or
++      enter event.
++      The time argument is a timestamp with millisecond
++      granularity, with an undefined base.
++
++      The button is a button code as defined in the Linux kernel's
++      linux/input-event-codes.h header file, e.g. BTN_LEFT.
++
++      Any 16-bit button code value is reserved for future additions to the
++      kernel's event code list. All other button codes above 0xFFFF are
++      currently undefined but may be used in future versions of this
++      protocol.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the button event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="button" type="uint" summary="button that produced the event"/>
++      <arg name="state" type="uint" enum="button_state" summary="physical state of the button"/>
++    </event>
++
++    <enum name="axis">
++      <description summary="axis types">
++      Describes the axis types of scroll events.
++      </description>
++      <entry name="vertical_scroll" value="0" summary="vertical axis"/>
++      <entry name="horizontal_scroll" value="1" summary="horizontal axis"/>
++    </enum>
++
++    <event name="axis">
++      <description summary="axis event">
++      Scroll and other axis notifications.
++
++      For scroll events (vertical and horizontal scroll axes), the
++      value parameter is the length of a vector along the specified
++      axis in a coordinate space identical to those of motion events,
++      representing a relative movement along the specified axis.
++
++      For devices that support movements non-parallel to axes multiple
++      axis events will be emitted.
++
++      When applicable, for example for touch pads, the server can
++      choose to emit scroll events where the motion vector is
++      equivalent to a motion event vector.
++
++      When applicable, a client can transform its content relative to the
++      scroll distance.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++      <arg name="value" type="fixed" summary="length of vector in surface-local coordinate space"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the pointer object">
++      Using this request a client can tell the server that it is not going to
++      use the pointer object anymore.
++
++      This request destroys the pointer proxy object, so clients must not call
++      wl_pointer_destroy() after using this request.
++      </description>
++    </request>
++
++    <!-- Version 5 additions -->
++
++    <event name="frame" since="5">
++      <description summary="end of a pointer event sequence">
++      Indicates the end of a set of events that logically belong together.
++      A client is expected to accumulate the data in all events within the
++      frame before proceeding.
++
++      All wl_pointer events before a wl_pointer.frame event belong
++      logically together. For example, in a diagonal scroll motion the
++      compositor will send an optional wl_pointer.axis_source event, two
++      wl_pointer.axis events (horizontal and vertical) and finally a
++      wl_pointer.frame event. The client may use this information to
++      calculate a diagonal vector for scrolling.
++
++      When multiple wl_pointer.axis events occur within the same frame,
++      the motion vector is the combined motion of all events.
++      When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
++      the same frame, this indicates that axis movement in one axis has
++      stopped but continues in the other axis.
++      When multiple wl_pointer.axis_stop events occur within the same
++      frame, this indicates that these axes stopped in the same instance.
++
++      A wl_pointer.frame event is sent for every logical event group,
++      even if the group only contains a single wl_pointer event.
++      Specifically, a client may get a sequence: motion, frame, button,
++      frame, axis, frame, axis_stop, frame.
++
++      The wl_pointer.enter and wl_pointer.leave events are logical events
++      generated by the compositor and not the hardware. These events are
++      also grouped by a wl_pointer.frame. When a pointer moves from one
++      surface to another, a compositor should group the
++      wl_pointer.leave event within the same wl_pointer.frame.
++      However, a client must not rely on wl_pointer.leave and
++      wl_pointer.enter being in the same wl_pointer.frame.
++      Compositor-specific policies may require the wl_pointer.leave and
++      wl_pointer.enter event being split across multiple wl_pointer.frame
++      groups.
++      </description>
++    </event>
++
++    <enum name="axis_source">
++      <description summary="axis source types">
++      Describes the source types for axis events. This indicates to the
++      client how an axis event was physically generated; a client may
++      adjust the user interface accordingly. For example, scroll events
++      from a "finger" source may be in a smooth coordinate space with
++      kinetic scrolling whereas a "wheel" source may be in discrete steps
++      of a number of lines.
++
++      The "continuous" axis source is a device generating events in a
++      continuous coordinate space, but using something other than a
++      finger. One example for this source is button-based scrolling where
++      the vertical motion of a device is converted to scroll events while
++      a button is held down.
++
++      The "wheel tilt" axis source indicates that the actual device is a
++      wheel but the scroll event is not caused by a rotation but a
++      (usually sideways) tilt of the wheel.
++      </description>
++      <entry name="wheel" value="0" summary="a physical wheel rotation" />
++      <entry name="finger" value="1" summary="finger on a touch surface" />
++      <entry name="continuous" value="2" summary="continuous coordinate space"/>
++      <entry name="wheel_tilt" value="3" summary="a physical wheel tilt" since="6"/>
++    </enum>
++
++    <event name="axis_source" since="5">
++      <description summary="axis source event">
++      Source information for scroll and other axes.
++
++      This event does not occur on its own. It is sent before a
++      wl_pointer.frame event and carries the source information for
++      all events within that frame.
++
++      The source specifies how this event was generated. If the source is
++      wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
++      sent when the user lifts the finger off the device.
++
++      If the source is wl_pointer.axis_source.wheel,
++      wl_pointer.axis_source.wheel_tilt or
++      wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
++      or may not be sent. Whether a compositor sends an axis_stop event
++      for these sources is hardware-specific and implementation-dependent;
++      clients must not rely on receiving an axis_stop event for these
++      scroll sources and should treat scroll sequences from these scroll
++      sources as unterminated by default.
++
++      This event is optional. If the source is unknown for a particular
++      axis event sequence, no event is sent.
++      Only one wl_pointer.axis_source event is permitted per frame.
++
++      The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++      not guaranteed.
++      </description>
++      <arg name="axis_source" type="uint" enum="axis_source" summary="source of the axis event"/>
++    </event>
++
++    <event name="axis_stop" since="5">
++      <description summary="axis stop event">
++      Stop notification for scroll and other axes.
++
++      For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
++      is sent to notify a client that the axis sequence has terminated.
++      This enables the client to implement kinetic scrolling.
++      See the wl_pointer.axis_source documentation for information on when
++      this event may be generated.
++
++      Any wl_pointer.axis events with the same axis_source after this
++      event should be considered as the start of a new axis motion.
++
++      The timestamp is to be interpreted identical to the timestamp in the
++      wl_pointer.axis event. The timestamp value may be the same as a
++      preceding wl_pointer.axis event.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
++    </event>
++
++    <event name="axis_discrete" since="5">
++      <description summary="axis click event">
++      Discrete step information for scroll and other axes.
++
++      This event carries the axis value of the wl_pointer.axis event in
++      discrete steps (e.g. mouse wheel clicks).
++
++      This event is deprecated with wl_pointer version 8 - this event is not
++      sent to clients supporting version 8 or later.
++
++      This event does not occur on its own, it is coupled with a
++      wl_pointer.axis event that represents this axis value on a
++      continuous scale. The protocol guarantees that each axis_discrete
++      event is always followed by exactly one axis event with the same
++      axis number within the same wl_pointer.frame. Note that the protocol
++      allows for other events to occur between the axis_discrete and
++      its coupled axis event, including other axis_discrete or axis
++      events. A wl_pointer.frame must not contain more than one axis_discrete
++      event per axis type.
++
++      This event is optional; continuous scrolling devices
++      like two-finger scrolling on touchpads do not have discrete
++      steps and do not generate this event.
++
++      The discrete value carries the directional information. e.g. a value
++      of -2 is two steps towards the negative direction of this axis.
++
++      The axis number is identical to the axis number in the associated
++      axis event.
++
++      The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++      not guaranteed.
++      </description>
++      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++      <arg name="discrete" type="int" summary="number of steps"/>
++    </event>
++
++    <event name="axis_value120" since="8">
++      <description summary="axis high-resolution scroll event">
++      Discrete high-resolution scroll information.
++
++      This event carries high-resolution wheel scroll information,
++      with each multiple of 120 representing one logical scroll step
++      (a wheel detent). For example, an axis_value120 of 30 is one quarter of
++      a logical scroll step in the positive direction, a value120 of
++      -240 are two logical scroll steps in the negative direction within the
++      same hardware event.
++      Clients that rely on discrete scrolling should accumulate the
++      value120 to multiples of 120 before processing the event.
++
++      The value120 must not be zero.
++
++      This event replaces the wl_pointer.axis_discrete event in clients
++      supporting wl_pointer version 8 or later.
++
++      Where a wl_pointer.axis_source event occurs in the same
++      wl_pointer.frame, the axis source applies to this event.
++
++      The order of wl_pointer.axis_value120 and wl_pointer.axis_source is
++      not guaranteed.
++      </description>
++      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++      <arg name="value120" type="int" summary="scroll distance as fraction of 120"/>
++    </event>
++  </interface>
++
++  <interface name="wl_keyboard" version="8">
++    <description summary="keyboard input device">
++      The wl_keyboard interface represents one or more keyboards
++      associated with a seat.
++    </description>
++
++    <enum name="keymap_format">
++      <description summary="keyboard mapping format">
++      This specifies the format of the keymap provided to the
++      client with the wl_keyboard.keymap event.
++      </description>
++      <entry name="no_keymap" value="0"
++           summary="no keymap; client must understand how to interpret the raw keycode"/>
++      <entry name="xkb_v1" value="1"
++           summary="libxkbcommon compatible, null-terminated string; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
++    </enum>
++
++    <event name="keymap">
++      <description summary="keyboard mapping">
++      This event provides a file descriptor to the client which can be
++      memory-mapped in read-only mode to provide a keyboard mapping
++      description.
++
++      From version 7 onwards, the fd must be mapped with MAP_PRIVATE by
++      the recipient, as MAP_SHARED may fail.
++      </description>
++      <arg name="format" type="uint" enum="keymap_format" summary="keymap format"/>
++      <arg name="fd" type="fd" summary="keymap file descriptor"/>
++      <arg name="size" type="uint" summary="keymap size, in bytes"/>
++    </event>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notification that this seat's keyboard focus is on a certain
++      surface.
++
++      The compositor must send the wl_keyboard.modifiers event after this
++      event.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
++      <arg name="keys" type="array" summary="the currently pressed keys"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notification that this seat's keyboard focus is no longer on
++      a certain surface.
++
++      The leave notification is sent before the enter notification
++      for the new focus.
++
++      After this event client must assume that all keys, including modifiers,
++      are lifted and also it must stop key repeating if there's some going on.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the leave event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
++    </event>
++
++    <enum name="key_state">
++      <description summary="physical key state">
++      Describes the physical state of a key that produced the key event.
++      </description>
++      <entry name="released" value="0" summary="key is not pressed"/>
++      <entry name="pressed" value="1" summary="key is pressed"/>
++    </enum>
++
++    <event name="key">
++      <description summary="key event">
++      A key was pressed or released.
++      The time argument is a timestamp with millisecond
++      granularity, with an undefined base.
++
++      The key is a platform-specific key code that can be interpreted
++      by feeding it to the keyboard mapping (see the keymap event).
++
++      If this event produces a change in modifiers, then the resulting
++      wl_keyboard.modifiers event must be sent after this event.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the key event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="key" type="uint" summary="key that produced the event"/>
++      <arg name="state" type="uint" enum="key_state" summary="physical state of the key"/>
++    </event>
++
++    <event name="modifiers">
++      <description summary="modifier and group state">
++      Notifies clients that the modifier and/or group state has
++      changed, and it should update its local state.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
++      <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
++      <arg name="mods_latched" type="uint" summary="latched modifiers"/>
++      <arg name="mods_locked" type="uint" summary="locked modifiers"/>
++      <arg name="group" type="uint" summary="keyboard layout"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the keyboard object"/>
++    </request>
++
++    <!-- Version 4 additions -->
++
++    <event name="repeat_info" since="4">
++      <description summary="repeat rate and delay">
++      Informs the client about the keyboard's repeat rate and delay.
++
++      This event is sent as soon as the wl_keyboard object has been created,
++      and is guaranteed to be received by the client before any key press
++      event.
++
++      Negative values for either rate or delay are illegal. A rate of zero
++      will disable any repeating (regardless of the value of delay).
++
++      This event can be sent later on as well with a new value if necessary,
++      so clients should continue listening for the event past the creation
++      of wl_keyboard.
++      </description>
++      <arg name="rate" type="int"
++         summary="the rate of repeating keys in characters per second"/>
++      <arg name="delay" type="int"
++         summary="delay in milliseconds since key down until repeating starts"/>
++    </event>
++  </interface>
++
++  <interface name="wl_touch" version="8">
++    <description summary="touchscreen input device">
++      The wl_touch interface represents a touchscreen
++      associated with a seat.
++
++      Touch interactions can consist of one or more contacts.
++      For each contact, a series of events is generated, starting
++      with a down event, followed by zero or more motion events,
++      and ending with an up event. Events relating to the same
++      contact point can be identified by the ID of the sequence.
++    </description>
++
++    <event name="down">
++      <description summary="touch down event and beginning of a touch sequence">
++      A new touch point has appeared on the surface. This touch point is
++      assigned a unique ID. Future events from this touch point reference
++      this ID. The ID ceases to be valid after a touch up event and may be
++      reused in the future.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the touch down event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface touched"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="up">
++      <description summary="end of a touch event sequence">
++      The touch point has disappeared. No further events will be sent for
++      this touch point and the touch point's ID is released and may be
++      reused in a future touch down event.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the touch up event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++    </event>
++
++    <event name="motion">
++      <description summary="update of touch point coordinates">
++      A touch point has changed coordinates.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="frame">
++      <description summary="end of touch frame event">
++      Indicates the end of a set of events that logically belong together.
++      A client is expected to accumulate the data in all events within the
++      frame before proceeding.
++
++      A wl_touch.frame terminates at least one event but otherwise no
++      guarantee is provided about the set of events within a frame. A client
++      must assume that any state not updated in a frame is unchanged from the
++      previously known state.
++      </description>
++    </event>
++
++    <event name="cancel">
++      <description summary="touch session cancelled">
++      Sent if the compositor decides the touch stream is a global
++      gesture. No further events are sent to the clients from that
++      particular gesture. Touch cancellation applies to all touch points
++      currently active on this client's surface. The client is
++      responsible for finalizing the touch points, future touch points on
++      this surface may reuse the touch point ID.
++      </description>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the touch object"/>
++    </request>
++
++    <!-- Version 6 additions -->
++
++    <event name="shape" since="6">
++      <description summary="update shape of touch point">
++      Sent when a touchpoint has changed its shape.
++
++      This event does not occur on its own. It is sent before a
++      wl_touch.frame event and carries the new shape information for
++      any previously reported, or new touch points of that frame.
++
++      Other events describing the touch point such as wl_touch.down,
++      wl_touch.motion or wl_touch.orientation may be sent within the
++      same wl_touch.frame. A client should treat these events as a single
++      logical touch point update. The order of wl_touch.shape,
++      wl_touch.orientation and wl_touch.motion is not guaranteed.
++      A wl_touch.down event is guaranteed to occur before the first
++      wl_touch.shape event for this touch ID but both events may occur within
++      the same wl_touch.frame.
++
++      A touchpoint shape is approximated by an ellipse through the major and
++      minor axis length. The major axis length describes the longer diameter
++      of the ellipse, while the minor axis length describes the shorter
++      diameter. Major and minor are orthogonal and both are specified in
++      surface-local coordinates. The center of the ellipse is always at the
++      touchpoint location as reported by wl_touch.down or wl_touch.move.
++
++      This event is only sent by the compositor if the touch device supports
++      shape reports. The client has to make reasonable assumptions about the
++      shape if it did not receive this event.
++      </description>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="major" type="fixed" summary="length of the major axis in surface-local coordinates"/>
++      <arg name="minor" type="fixed" summary="length of the minor axis in surface-local coordinates"/>
++    </event>
++
++    <event name="orientation" since="6">
++      <description summary="update orientation of touch point">
++      Sent when a touchpoint has changed its orientation.
++
++      This event does not occur on its own. It is sent before a
++      wl_touch.frame event and carries the new shape information for
++      any previously reported, or new touch points of that frame.
++
++      Other events describing the touch point such as wl_touch.down,
++      wl_touch.motion or wl_touch.shape may be sent within the
++      same wl_touch.frame. A client should treat these events as a single
++      logical touch point update. The order of wl_touch.shape,
++      wl_touch.orientation and wl_touch.motion is not guaranteed.
++      A wl_touch.down event is guaranteed to occur before the first
++      wl_touch.orientation event for this touch ID but both events may occur
++      within the same wl_touch.frame.
++
++      The orientation describes the clockwise angle of a touchpoint's major
++      axis to the positive surface y-axis and is normalized to the -180 to
++      +180 degree range. The granularity of orientation depends on the touch
++      device, some devices only support binary rotation values between 0 and
++      90 degrees.
++
++      This event is only sent by the compositor if the touch device supports
++      orientation reports.
++      </description>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="orientation" type="fixed" summary="angle between major axis and positive surface y-axis in degrees"/>
++    </event>
++  </interface>
++
++  <interface name="wl_output" version="4">
++    <description summary="compositor output region">
++      An output describes part of the compositor geometry.  The
++      compositor works in the 'compositor coordinate system' and an
++      output corresponds to a rectangular area in that space that is
++      actually visible.  This typically corresponds to a monitor that
++      displays part of the compositor space.  This object is published
++      as global during start up, or when a monitor is hotplugged.
++    </description>
++
++    <enum name="subpixel">
++      <description summary="subpixel geometry information">
++      This enumeration describes how the physical
++      pixels on an output are laid out.
++      </description>
++      <entry name="unknown" value="0" summary="unknown geometry"/>
++      <entry name="none" value="1" summary="no geometry"/>
++      <entry name="horizontal_rgb" value="2" summary="horizontal RGB"/>
++      <entry name="horizontal_bgr" value="3" summary="horizontal BGR"/>
++      <entry name="vertical_rgb" value="4" summary="vertical RGB"/>
++      <entry name="vertical_bgr" value="5" summary="vertical BGR"/>
++    </enum>
++
++    <enum name="transform">
++      <description summary="transform from framebuffer to output">
++      This describes the transform that a compositor will apply to a
++      surface to compensate for the rotation or mirroring of an
++      output device.
++
++      The flipped values correspond to an initial flip around a
++      vertical axis followed by rotation.
++
++      The purpose is mainly to allow clients to render accordingly and
++      tell the compositor, so that for fullscreen surfaces, the
++      compositor will still be able to scan out directly from client
++      surfaces.
++      </description>
++      <entry name="normal" value="0" summary="no transform"/>
++      <entry name="90" value="1" summary="90 degrees counter-clockwise"/>
++      <entry name="180" value="2" summary="180 degrees counter-clockwise"/>
++      <entry name="270" value="3" summary="270 degrees counter-clockwise"/>
++      <entry name="flipped" value="4" summary="180 degree flip around a vertical axis"/>
++      <entry name="flipped_90" value="5" summary="flip and rotate 90 degrees counter-clockwise"/>
++      <entry name="flipped_180" value="6" summary="flip and rotate 180 degrees counter-clockwise"/>
++      <entry name="flipped_270" value="7" summary="flip and rotate 270 degrees counter-clockwise"/>
++    </enum>
++
++    <event name="geometry">
++      <description summary="properties of the output">
++      The geometry event describes geometric properties of the output.
++      The event is sent when binding to the output object and whenever
++      any of the properties change.
++
++      The physical size can be set to zero if it doesn't make sense for this
++      output (e.g. for projectors or virtual outputs).
++
++      The geometry event will be followed by a done event (starting from
++      version 2).
++
++      Note: wl_output only advertises partial information about the output
++      position and identification. Some compositors, for instance those not
++      implementing a desktop-style output layout or those exposing virtual
++      outputs, might fake this information. Instead of using x and y, clients
++      should use xdg_output.logical_position. Instead of using make and model,
++      clients should use name and description.
++      </description>
++      <arg name="x" type="int"
++         summary="x position within the global compositor space"/>
++      <arg name="y" type="int"
++         summary="y position within the global compositor space"/>
++      <arg name="physical_width" type="int"
++         summary="width in millimeters of the output"/>
++      <arg name="physical_height" type="int"
++         summary="height in millimeters of the output"/>
++      <arg name="subpixel" type="int" enum="subpixel"
++         summary="subpixel orientation of the output"/>
++      <arg name="make" type="string"
++         summary="textual description of the manufacturer"/>
++      <arg name="model" type="string"
++         summary="textual description of the model"/>
++      <arg name="transform" type="int" enum="transform"
++         summary="transform that maps framebuffer to output"/>
++    </event>
++
++    <enum name="mode" bitfield="true">
++      <description summary="mode information">
++      These flags describe properties of an output mode.
++      They are used in the flags bitfield of the mode event.
++      </description>
++      <entry name="current" value="0x1"
++           summary="indicates this is the current mode"/>
++      <entry name="preferred" value="0x2"
++           summary="indicates this is the preferred mode"/>
++    </enum>
++
++    <event name="mode">
++      <description summary="advertise available modes for the output">
++      The mode event describes an available mode for the output.
++
++      The event is sent when binding to the output object and there
++      will always be one mode, the current mode.  The event is sent
++      again if an output changes mode, for the mode that is now
++      current.  In other words, the current mode is always the last
++      mode that was received with the current flag set.
++
++      Non-current modes are deprecated. A compositor can decide to only
++      advertise the current mode and never send other modes. Clients
++      should not rely on non-current modes.
++
++      The size of a mode is given in physical hardware units of
++      the output device. This is not necessarily the same as
++      the output size in the global compositor space. For instance,
++      the output may be scaled, as described in wl_output.scale,
++      or transformed, as described in wl_output.transform. Clients
++      willing to retrieve the output size in the global compositor
++      space should use xdg_output.logical_size instead.
++
++      The vertical refresh rate can be set to zero if it doesn't make
++      sense for this output (e.g. for virtual outputs).
++
++      The mode event will be followed by a done event (starting from
++      version 2).
++
++      Clients should not use the refresh rate to schedule frames. Instead,
++      they should use the wl_surface.frame event or the presentation-time
++      protocol.
++
++      Note: this information is not always meaningful for all outputs. Some
++      compositors, such as those exposing virtual outputs, might fake the
++      refresh rate or the size.
++      </description>
++      <arg name="flags" type="uint" enum="mode" summary="bitfield of mode flags"/>
++      <arg name="width" type="int" summary="width of the mode in hardware units"/>
++      <arg name="height" type="int" summary="height of the mode in hardware units"/>
++      <arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <event name="done" since="2">
++      <description summary="sent all information about output">
++      This event is sent after all other properties have been
++      sent after binding to the output object and after any
++      other property changes done after that. This allows
++      changes to the output properties to be seen as
++      atomic, even if they happen via multiple events.
++      </description>
++    </event>
++
++    <event name="scale" since="2">
++      <description summary="output scaling properties">
++      This event contains scaling geometry information
++      that is not in the geometry event. It may be sent after
++      binding the output object or if the output scale changes
++      later. If it is not sent, the client should assume a
++      scale of 1.
++
++      A scale larger than 1 means that the compositor will
++      automatically scale surface buffers by this amount
++      when rendering. This is used for very high resolution
++      displays where applications rendering at the native
++      resolution would be too small to be legible.
++
++      It is intended that scaling aware clients track the
++      current output of a surface, and if it is on a scaled
++      output it should use wl_surface.set_buffer_scale with
++      the scale of the output. That way the compositor can
++      avoid scaling the surface, and the client can supply
++      a higher detail image.
++
++      The scale event will be followed by a done event.
++      </description>
++      <arg name="factor" type="int" summary="scaling factor of output"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the output object">
++      Using this request a client can tell the server that it is not going to
++      use the output object anymore.
++      </description>
++    </request>
++
++    <!-- Version 4 additions -->
++
++    <event name="name" since="4">
++      <description summary="name of this output">
++      Many compositors will assign user-friendly names to their outputs, show
++      them to the user, allow the user to refer to an output, etc. The client
++      may wish to know this name as well to offer the user similar behaviors.
++
++      The name is a UTF-8 string with no convention defined for its contents.
++      Each name is unique among all wl_output globals. The name is only
++      guaranteed to be unique for the compositor instance.
++
++      The same output name is used for all clients for a given wl_output
++      global. Thus, the name can be shared across processes to refer to a
++      specific wl_output global.
++
++      The name is not guaranteed to be persistent across sessions, thus cannot
++      be used to reliably identify an output in e.g. configuration files.
++
++      Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc. However, do
++      not assume that the name is a reflection of an underlying DRM connector,
++      X11 connection, etc.
++
++      The name event is sent after binding the output object. This event is
++      only sent once per output object, and the name does not change over the
++      lifetime of the wl_output global.
++
++      Compositors may re-use the same output name if the wl_output global is
++      destroyed and re-created later. Compositors should avoid re-using the
++      same name if possible.
++
++      The name event will be followed by a done event.
++      </description>
++      <arg name="name" type="string" summary="output name"/>
++    </event>
++
++    <event name="description" since="4">
++      <description summary="human-readable description of this output">
++      Many compositors can produce human-readable descriptions of their
++      outputs. The client may wish to know this description as well, e.g. for
++      output selection purposes.
++
++      The description is a UTF-8 string with no convention defined for its
++      contents. The description is not guaranteed to be unique among all
++      wl_output globals. Examples might include 'Foocorp 11" Display' or
++      'Virtual X11 output via :1'.
++
++      The description event is sent after binding the output object and
++      whenever the description changes. The description is optional, and may
++      not be sent at all.
++
++      The description event will be followed by a done event.
++      </description>
++      <arg name="description" type="string" summary="output description"/>
++    </event>
++  </interface>
++
++  <interface name="wl_region" version="1">
++    <description summary="region interface">
++      A region object describes an area.
++
++      Region objects are used to describe the opaque and input
++      regions of a surface.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy region">
++      Destroy the region.  This will invalidate the object ID.
++      </description>
++    </request>
++
++    <request name="add">
++      <description summary="add rectangle to region">
++      Add the specified rectangle to the region.
++      </description>
++      <arg name="x" type="int" summary="region-local x coordinate"/>
++      <arg name="y" type="int" summary="region-local y coordinate"/>
++      <arg name="width" type="int" summary="rectangle width"/>
++      <arg name="height" type="int" summary="rectangle height"/>
++    </request>
++
++    <request name="subtract">
++      <description summary="subtract rectangle from region">
++      Subtract the specified rectangle from the region.
++      </description>
++      <arg name="x" type="int" summary="region-local x coordinate"/>
++      <arg name="y" type="int" summary="region-local y coordinate"/>
++      <arg name="width" type="int" summary="rectangle width"/>
++      <arg name="height" type="int" summary="rectangle height"/>
++    </request>
++  </interface>
++
++  <interface name="wl_subcompositor" version="1">
++    <description summary="sub-surface compositing">
++      The global interface exposing sub-surface compositing capabilities.
++      A wl_surface, that has sub-surfaces associated, is called the
++      parent surface. Sub-surfaces can be arbitrarily nested and create
++      a tree of sub-surfaces.
++
++      The root surface in a tree of sub-surfaces is the main
++      surface. The main surface cannot be a sub-surface, because
++      sub-surfaces must always have a parent.
++
++      A main surface with its sub-surfaces forms a (compound) window.
++      For window management purposes, this set of wl_surface objects is
++      to be considered as a single window, and it should also behave as
++      such.
++
++      The aim of sub-surfaces is to offload some of the compositing work
++      within a window from clients to the compositor. A prime example is
++      a video player with decorations and video in separate wl_surface
++      objects. This should allow the compositor to pass YUV video buffer
++      processing to dedicated overlay hardware when possible.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unbind from the subcompositor interface">
++      Informs the server that the client will not be using this
++      protocol object anymore. This does not affect any other
++      objects, wl_subsurface objects included.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="bad_surface" value="0"
++           summary="the to-be sub-surface is invalid"/>
++    </enum>
++
++    <request name="get_subsurface">
++      <description summary="give a surface the role sub-surface">
++      Create a sub-surface interface for the given surface, and
++      associate it with the given parent surface. This turns a
++      plain wl_surface into a sub-surface.
++
++      The to-be sub-surface must not already have another role, and it
++      must not have an existing wl_subsurface object. Otherwise a protocol
++      error is raised.
++
++      Adding sub-surfaces to a parent is a double-buffered operation on the
++      parent (see wl_surface.commit). The effect of adding a sub-surface
++      becomes visible on the next time the state of the parent surface is
++      applied.
++
++      This request modifies the behaviour of wl_surface.commit request on
++      the sub-surface, see the documentation on wl_subsurface interface.
++      </description>
++      <arg name="id" type="new_id" interface="wl_subsurface"
++         summary="the new sub-surface object ID"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface to be turned into a sub-surface"/>
++      <arg name="parent" type="object" interface="wl_surface"
++         summary="the parent surface"/>
++    </request>
++  </interface>
++
++  <interface name="wl_subsurface" version="1">
++    <description summary="sub-surface interface to a wl_surface">
++      An additional interface to a wl_surface object, which has been
++      made a sub-surface. A sub-surface has one parent surface. A
++      sub-surface's size and position are not limited to that of the parent.
++      Particularly, a sub-surface is not automatically clipped to its
++      parent's area.
++
++      A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++      and the parent surface is mapped. The order of which one happens
++      first is irrelevant. A sub-surface is hidden if the parent becomes
++      hidden, or if a NULL wl_buffer is applied. These rules apply
++      recursively through the tree of surfaces.
++
++      The behaviour of a wl_surface.commit request on a sub-surface
++      depends on the sub-surface's mode. The possible modes are
++      synchronized and desynchronized, see methods
++      wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++      mode caches the wl_surface state to be applied when the parent's
++      state gets applied, and desynchronized mode applies the pending
++      wl_surface state directly. A sub-surface is initially in the
++      synchronized mode.
++
++      Sub-surfaces also have another kind of state, which is managed by
++      wl_subsurface requests, as opposed to wl_surface requests. This
++      state includes the sub-surface position relative to the parent
++      surface (wl_subsurface.set_position), and the stacking order of
++      the parent and its sub-surfaces (wl_subsurface.place_above and
++      .place_below). This state is applied when the parent surface's
++      wl_surface state is applied, regardless of the sub-surface's mode.
++      As the exception, set_sync and set_desync are effective immediately.
++
++      The main surface can be thought to be always in desynchronized mode,
++      since it does not have a parent in the sub-surfaces sense.
++
++      Even if a sub-surface is in desynchronized mode, it will behave as
++      in synchronized mode, if its parent surface behaves as in
++      synchronized mode. This rule is applied recursively throughout the
++      tree of surfaces. This means, that one can set a sub-surface into
++      synchronized mode, and then assume that all its child and grand-child
++      sub-surfaces are synchronized, too, without explicitly setting them.
++
++      If the wl_surface associated with the wl_subsurface is destroyed, the
++      wl_subsurface object becomes inert. Note, that destroying either object
++      takes effect immediately. If you need to synchronize the removal
++      of a sub-surface to the parent surface update, unmap the sub-surface
++      first by attaching a NULL wl_buffer, update parent, and then destroy
++      the sub-surface.
++
++      If the parent wl_surface object is destroyed, the sub-surface is
++      unmapped.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove sub-surface interface">
++      The sub-surface interface is removed from the wl_surface object
++      that was turned into a sub-surface with a
++      wl_subcompositor.get_subsurface request. The wl_surface's association
++      to the parent is deleted, and the wl_surface loses its role as
++      a sub-surface. The wl_surface is unmapped immediately.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="bad_surface" value="0"
++           summary="wl_surface is not a sibling or the parent"/>
++    </enum>
++
++    <request name="set_position">
++      <description summary="reposition the sub-surface">
++      This schedules a sub-surface position change.
++      The sub-surface will be moved so that its origin (top left
++      corner pixel) will be at the location x, y of the parent surface
++      coordinate system. The coordinates are not restricted to the parent
++      surface area. Negative values are allowed.
++
++      The scheduled coordinates will take effect whenever the state of the
++      parent surface is applied. When this happens depends on whether the
++      parent surface is in synchronized mode or not. See
++      wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++
++      If more than one set_position request is invoked by the client before
++      the commit of the parent surface, the position of a new request always
++      replaces the scheduled position from any previous request.
++
++      The initial position is 0, 0.
++      </description>
++      <arg name="x" type="int" summary="x coordinate in the parent surface"/>
++      <arg name="y" type="int" summary="y coordinate in the parent surface"/>
++    </request>
++
++    <request name="place_above">
++      <description summary="restack the sub-surface">
++      This sub-surface is taken from the stack, and put back just
++      above the reference surface, changing the z-order of the sub-surfaces.
++      The reference surface must be one of the sibling surfaces, or the
++      parent surface. Using any other surface, including this sub-surface,
++      will cause a protocol error.
++
++      The z-order is double-buffered. Requests are handled in order and
++      applied immediately to a pending state. The final pending state is
++      copied to the active state the next time the state of the parent
++      surface is applied. When this happens depends on whether the parent
++      surface is in synchronized mode or not. See wl_subsurface.set_sync and
++      wl_subsurface.set_desync for details.
++
++      A new sub-surface is initially added as the top-most in the stack
++      of its siblings and parent.
++      </description>
++      <arg name="sibling" type="object" interface="wl_surface"
++         summary="the reference surface"/>
++    </request>
++
++    <request name="place_below">
++      <description summary="restack the sub-surface">
++      The sub-surface is placed just below the reference surface.
++      See wl_subsurface.place_above.
++      </description>
++      <arg name="sibling" type="object" interface="wl_surface"
++         summary="the reference surface"/>
++    </request>
++
++    <request name="set_sync">
++      <description summary="set sub-surface to synchronized mode">
++      Change the commit behaviour of the sub-surface to synchronized
++      mode, also described as the parent dependent mode.
++
++      In synchronized mode, wl_surface.commit on a sub-surface will
++      accumulate the committed state in a cache, but the state will
++      not be applied and hence will not change the compositor output.
++      The cached state is applied to the sub-surface immediately after
++      the parent surface's state is applied. This ensures atomic
++      updates of the parent and all its synchronized sub-surfaces.
++      Applying the cached state will invalidate the cache, so further
++      parent surface commits do not (re-)apply old state.
++
++      See wl_subsurface for the recursive effect of this mode.
++      </description>
++    </request>
++
++    <request name="set_desync">
++      <description summary="set sub-surface to desynchronized mode">
++      Change the commit behaviour of the sub-surface to desynchronized
++      mode, also described as independent or freely running mode.
++
++      In desynchronized mode, wl_surface.commit on a sub-surface will
++      apply the pending state directly, without caching, as happens
++      normally with a wl_surface. Calling wl_surface.commit on the
++      parent surface has no effect on the sub-surface's wl_surface
++      state. This mode allows a sub-surface to be updated on its own.
++
++      If cached state exists when wl_surface.commit is called in
++      desynchronized mode, the pending state is added to the cached
++      state, and applied as a whole. This invalidates the cache.
++
++      Note: even if a sub-surface is set to desynchronized, a parent
++      sub-surface may override it to behave as synchronized. For details,
++      see wl_subsurface.
++
++      If a surface's parent surface behaves as desynchronized, then
++      the cached state is applied on set_desync.
++      </description>
++    </request>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..59e6eb07ee7176f02a98121f450ab5cb9f92edef
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,70 @@@
++#!/bin/sh -eu
++
++build_dir=build-release
++
++if ! type glab >/dev/null; then
++      echo "glab is needed to create a release"
++      exit 1
++fi
++
++case "$(git rev-parse --abbrev-ref HEAD)" in
++main | [0-9]*.[0-9]*)
++      ;;
++*)
++      echo "Not on the main or a stable branch"
++      exit 1
++esac
++
++if [ -n "$(git log @{upstream}..)" ]; then
++      echo "The main branch has unpushed commits"
++      exit 1
++fi
++
++meson_options=""
++if [ -e "$build_dir" ]; then
++      meson_options="$meson_options --wipe"
++fi
++meson setup "$build_dir" $meson_options
++
++prev_version="$(git describe --tags --abbrev=0)"
++version="$(meson introspect "$build_dir" --projectinfo | jq -r .version)"
++if [ "$version" = "$prev_version" ]; then
++      echo "Version not bumped"
++      exit 1
++fi
++
++ninja -C "$build_dir" dist
++
++archive_name="wayland-$version.tar.xz"
++archive_path="$build_dir/meson-dist/$archive_name"
++gpg --detach-sig "$archive_path"
++
++sha256="$(cd $build_dir/meson-dist && sha256sum $archive_name)"
++sha512="$(cd $build_dir/meson-dist && sha512sum $archive_name)"
++archive_url="https://gitlab.freedesktop.org/wayland/wayland/-/releases/$version/downloads/$archive_name"
++announce_path="$build_dir/meson-dist/wayland-$version-announce.eml"
++cat >"$announce_path" <<EOF
++To: <wayland-devel@lists.freedesktop.org>
++Subject: [ANNOUNCE] wayland $version
++
++`git shortlog --no-merges "$prev_version.."`
++
++git tag: $version
++
++$archive_url
++SHA256: $sha256
++SHA512: $sha512
++PGP:    $archive_url.sig
++EOF
++
++echo "Release announcement written to $announce_path"
++
++echo -n "Release wayland $version? [y/N] "
++read answer
++if [ "$answer" != "y" ]; then
++      exit 1
++fi
++
++git tag -s -m "$version" "$version"
++git push --tags
++glab release create "$version" "$archive_path"* --notes ""
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..e93f53dda79b2684afd4a588c95885fc61f8b14f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,62 @@@
++To make a release of Wayland, follow these steps.
++
++  0.  Verify the test suites and codebase checks pass.  All of the
++      tests should either pass or skip.
++
++      $ ninja -C build/ test
++
++  1.  Update the first stanza of meson.build to the intended version.
++
++      Then commit your changes:
++
++      $ export RELEASE_NUMBER="x.y.z"
++      $ export RELEASE_NAME="[alpha|beta|RC1|RC2|official|point]"
++      $ git status
++      $ git commit meson.build -m "build: bump to version $RELEASE_NUMBER for the $RELEASE_NAME release"
++      $ git push
++
++  2.  Run the release.sh script to generate the tarballs, sign and
++      upload them, and generate a release announcement template.
++
++  3.  Compose the release announcements.  The script will generate a
++      wayland-x.y.z-announce.eml file with a list of changes and tags.
++      Prepend it with a human-readable listing of the most notable
++      changes. For x.y.0 releases, indicate the schedule for the x.y+1.0
++      release.
++
++  4.  PGP sign the release announcements and send them to
++      wayland-devel@lists.freedesktop.org
++
++  5.  Update releases.html in wayland-web with links to tarballs and
++      the release email URL.
++
++      The wl_register_release script in wayland-web will generate an HTML
++      snippet that can be pasted into releases.html (or e.g. in emacs
++      insert it via "C-u M-! scripts/wl_register_release x.y.z") and
++      customized.
++
++      Once satisfied:
++
++      $ git commit ./releases.html -m "releases: Add ${RELEASE_NUMBER} release"
++      $ git push
++      $ ./deploy
++
++For x.y.0 releases, also create the release series x.y branch.  The x.y
++branch is for bug fixes and conservative changes to the x.y.0 release,
++and is where we create x.y.z releases from.  Creating the x.y branch
++opens up master for new development and lets new development move on.
++We've done this both after the x.y.0 release (to focus development on
++bug fixing for the x.y.1 release for a little longer) or before the
++x.y.0 release (like we did with the 1.5.0 release, to unblock master
++development early).
++
++    $ git branch x.y [sha]
++    $ git push origin x.y
++
++The master branch's meson.build version should always be (at least)
++x.y.90, with x.y being the most recent stable branch.  The stable
++branch's meson.build version is just whatever was most recently
++released from that branch.
++
++For stable branches, we commit fixes to master first, then cherry-pick
++them back to the stable branch.
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..128e4f7ce7294b1ab21061580a5962b78594bafa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2 @@@
++*.dtd.embed
++/wayland-version.h
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ceaeac14cecfed7cbfa0c8cedd4903ed61afd66c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1389 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <math.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <stdio.h>
++#include <errno.h>
++#include <sys/uio.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <time.h>
++#include <ffi.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-os.h"
++
++static inline uint32_t
++div_roundup(uint32_t n, size_t a)
++{
++      /* The cast to uint64_t is necessary to prevent overflow when rounding
++       * values close to UINT32_MAX. After the division it is again safe to
++       * cast back to uint32_t.
++       */
++      return (uint32_t) (((uint64_t) n + (a - 1)) / a);
++}
++
++struct wl_ring_buffer {
++      char data[4096];
++      uint32_t head, tail;
++};
++
++#define MASK(i) ((i) & 4095)
++
++#define MAX_FDS_OUT   28
++#define CLEN          (CMSG_LEN(MAX_FDS_OUT * sizeof(int32_t)))
++
++struct wl_connection {
++      struct wl_ring_buffer in, out;
++      struct wl_ring_buffer fds_in, fds_out;
++      int fd;
++      int want_flush;
++};
++
++static int
++ring_buffer_put(struct wl_ring_buffer *b, const void *data, size_t count)
++{
++      uint32_t head, size;
++
++      if (count > sizeof(b->data)) {
++              wl_log("Data too big for buffer (%d > %d).\n",
++                     count, sizeof(b->data));
++              errno = E2BIG;
++              return -1;
++      }
++
++      head = MASK(b->head);
++      if (head + count <= sizeof b->data) {
++              memcpy(b->data + head, data, count);
++      } else {
++              size = sizeof b->data - head;
++              memcpy(b->data + head, data, size);
++              memcpy(b->data, (const char *) data + size, count - size);
++      }
++
++      b->head += count;
++
++      return 0;
++}
++
++static void
++ring_buffer_put_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
++{
++      uint32_t head, tail;
++
++      head = MASK(b->head);
++      tail = MASK(b->tail);
++      if (head < tail) {
++              iov[0].iov_base = b->data + head;
++              iov[0].iov_len = tail - head;
++              *count = 1;
++      } else if (tail == 0) {
++              iov[0].iov_base = b->data + head;
++              iov[0].iov_len = sizeof b->data - head;
++              *count = 1;
++      } else {
++              iov[0].iov_base = b->data + head;
++              iov[0].iov_len = sizeof b->data - head;
++              iov[1].iov_base = b->data;
++              iov[1].iov_len = tail;
++              *count = 2;
++      }
++}
++
++static void
++ring_buffer_get_iov(struct wl_ring_buffer *b, struct iovec *iov, int *count)
++{
++      uint32_t head, tail;
++
++      head = MASK(b->head);
++      tail = MASK(b->tail);
++      if (tail < head) {
++              iov[0].iov_base = b->data + tail;
++              iov[0].iov_len = head - tail;
++              *count = 1;
++      } else if (head == 0) {
++              iov[0].iov_base = b->data + tail;
++              iov[0].iov_len = sizeof b->data - tail;
++              *count = 1;
++      } else {
++              iov[0].iov_base = b->data + tail;
++              iov[0].iov_len = sizeof b->data - tail;
++              iov[1].iov_base = b->data;
++              iov[1].iov_len = head;
++              *count = 2;
++      }
++}
++
++static void
++ring_buffer_copy(struct wl_ring_buffer *b, void *data, size_t count)
++{
++      uint32_t tail, size;
++
++      tail = MASK(b->tail);
++      if (tail + count <= sizeof b->data) {
++              memcpy(data, b->data + tail, count);
++      } else {
++              size = sizeof b->data - tail;
++              memcpy(data, b->data + tail, size);
++              memcpy((char *) data + size, b->data, count - size);
++      }
++}
++
++static uint32_t
++ring_buffer_size(struct wl_ring_buffer *b)
++{
++      return b->head - b->tail;
++}
++
++struct wl_connection *
++wl_connection_create(int fd)
++{
++      struct wl_connection *connection;
++
++      connection = zalloc(sizeof *connection);
++      if (connection == NULL)
++              return NULL;
++
++      connection->fd = fd;
++
++      return connection;
++}
++
++static void
++close_fds(struct wl_ring_buffer *buffer, int max)
++{
++      int32_t fds[sizeof(buffer->data) / sizeof(int32_t)], i, count;
++      size_t size;
++
++      size = ring_buffer_size(buffer);
++      if (size == 0)
++              return;
++
++      ring_buffer_copy(buffer, fds, size);
++      count = size / sizeof fds[0];
++      if (max > 0 && max < count)
++              count = max;
++      size = count * sizeof fds[0];
++      for (i = 0; i < count; i++)
++              close(fds[i]);
++      buffer->tail += size;
++}
++
++void
++wl_connection_close_fds_in(struct wl_connection *connection, int max)
++{
++      close_fds(&connection->fds_in, max);
++}
++
++int
++wl_connection_destroy(struct wl_connection *connection)
++{
++      int fd = connection->fd;
++
++      close_fds(&connection->fds_out, -1);
++      close_fds(&connection->fds_in, -1);
++      free(connection);
++
++      return fd;
++}
++
++void
++wl_connection_copy(struct wl_connection *connection, void *data, size_t size)
++{
++      ring_buffer_copy(&connection->in, data, size);
++}
++
++void
++wl_connection_consume(struct wl_connection *connection, size_t size)
++{
++      connection->in.tail += size;
++}
++
++static void
++build_cmsg(struct wl_ring_buffer *buffer, char *data, size_t *clen)
++{
++      struct cmsghdr *cmsg;
++      size_t size;
++
++      size = ring_buffer_size(buffer);
++      if (size > MAX_FDS_OUT * sizeof(int32_t))
++              size = MAX_FDS_OUT * sizeof(int32_t);
++
++      if (size > 0) {
++              cmsg = (struct cmsghdr *) data;
++              cmsg->cmsg_level = SOL_SOCKET;
++              cmsg->cmsg_type = SCM_RIGHTS;
++              cmsg->cmsg_len = CMSG_LEN(size);
++              ring_buffer_copy(buffer, CMSG_DATA(cmsg), size);
++              *clen = cmsg->cmsg_len;
++      } else {
++              *clen = 0;
++      }
++}
++
++static int
++decode_cmsg(struct wl_ring_buffer *buffer, struct msghdr *msg)
++{
++      struct cmsghdr *cmsg;
++      size_t size, max, i;
++      int overflow = 0;
++
++      for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL;
++           cmsg = CMSG_NXTHDR(msg, cmsg)) {
++              if (cmsg->cmsg_level != SOL_SOCKET ||
++                  cmsg->cmsg_type != SCM_RIGHTS)
++                      continue;
++
++              size = cmsg->cmsg_len - CMSG_LEN(0);
++              max = sizeof(buffer->data) - ring_buffer_size(buffer);
++              if (size > max || overflow) {
++                      overflow = 1;
++                      size /= sizeof(int32_t);
++                      for (i = 0; i < size; i++)
++                              close(((int*)CMSG_DATA(cmsg))[i]);
++              } else if (ring_buffer_put(buffer, CMSG_DATA(cmsg), size) < 0) {
++                              return -1;
++              }
++      }
++
++      if (overflow) {
++              errno = EOVERFLOW;
++              return -1;
++      }
++
++      return 0;
++}
++
++int
++wl_connection_flush(struct wl_connection *connection)
++{
++      struct iovec iov[2];
++      struct msghdr msg = {0};
++      char cmsg[CLEN];
++      int len = 0, count;
++      size_t clen;
++      uint32_t tail;
++
++      if (!connection->want_flush)
++              return 0;
++
++      tail = connection->out.tail;
++      while (connection->out.head - connection->out.tail > 0) {
++              ring_buffer_get_iov(&connection->out, iov, &count);
++
++              build_cmsg(&connection->fds_out, cmsg, &clen);
++
++              msg.msg_iov = iov;
++              msg.msg_iovlen = count;
++              msg.msg_control = (clen > 0) ? cmsg : NULL;
++              msg.msg_controllen = clen;
++
++              do {
++                      len = sendmsg(connection->fd, &msg,
++                                    MSG_NOSIGNAL | MSG_DONTWAIT);
++              } while (len == -1 && errno == EINTR);
++
++              if (len == -1)
++                      return -1;
++
++              close_fds(&connection->fds_out, MAX_FDS_OUT);
++
++              connection->out.tail += len;
++      }
++
++      connection->want_flush = 0;
++
++      return connection->out.head - tail;
++}
++
++uint32_t
++wl_connection_pending_input(struct wl_connection *connection)
++{
++      return ring_buffer_size(&connection->in);
++}
++
++int
++wl_connection_read(struct wl_connection *connection)
++{
++      struct iovec iov[2];
++      struct msghdr msg;
++      char cmsg[CLEN];
++      int len, count, ret;
++
++      if (ring_buffer_size(&connection->in) >= sizeof(connection->in.data)) {
++              errno = EOVERFLOW;
++              return -1;
++      }
++
++      ring_buffer_put_iov(&connection->in, iov, &count);
++
++      msg.msg_name = NULL;
++      msg.msg_namelen = 0;
++      msg.msg_iov = iov;
++      msg.msg_iovlen = count;
++      msg.msg_control = cmsg;
++      msg.msg_controllen = sizeof cmsg;
++      msg.msg_flags = 0;
++
++      do {
++              len = wl_os_recvmsg_cloexec(connection->fd, &msg, MSG_DONTWAIT);
++      } while (len < 0 && errno == EINTR);
++
++      if (len <= 0)
++              return len;
++
++      ret = decode_cmsg(&connection->fds_in, &msg);
++      if (ret)
++              return -1;
++
++      connection->in.head += len;
++
++      return wl_connection_pending_input(connection);
++}
++
++int
++wl_connection_write(struct wl_connection *connection,
++                  const void *data, size_t count)
++{
++      if (connection->out.head - connection->out.tail +
++          count > ARRAY_LENGTH(connection->out.data)) {
++              connection->want_flush = 1;
++              if (wl_connection_flush(connection) < 0)
++                      return -1;
++      }
++
++      if (ring_buffer_put(&connection->out, data, count) < 0)
++              return -1;
++
++      connection->want_flush = 1;
++
++      return 0;
++}
++
++int
++wl_connection_queue(struct wl_connection *connection,
++                  const void *data, size_t count)
++{
++      if (connection->out.head - connection->out.tail +
++          count > ARRAY_LENGTH(connection->out.data)) {
++              connection->want_flush = 1;
++              if (wl_connection_flush(connection) < 0)
++                      return -1;
++      }
++
++      return ring_buffer_put(&connection->out, data, count);
++}
++
++int
++wl_message_count_arrays(const struct wl_message *message)
++{
++      int i, arrays;
++
++      for (i = 0, arrays = 0; message->signature[i]; i++) {
++              if (message->signature[i] == 'a')
++                      arrays++;
++      }
++
++      return arrays;
++}
++
++int
++wl_connection_get_fd(struct wl_connection *connection)
++{
++      return connection->fd;
++}
++
++static int
++wl_connection_put_fd(struct wl_connection *connection, int32_t fd)
++{
++      if (ring_buffer_size(&connection->fds_out) == MAX_FDS_OUT * sizeof fd) {
++              connection->want_flush = 1;
++              if (wl_connection_flush(connection) < 0)
++                      return -1;
++      }
++
++      return ring_buffer_put(&connection->fds_out, &fd, sizeof fd);
++}
++
++const char *
++get_next_argument(const char *signature, struct argument_details *details)
++{
++      details->nullable = 0;
++      for(; *signature; ++signature) {
++              switch(*signature) {
++              case 'i':
++              case 'u':
++              case 'f':
++              case 's':
++              case 'o':
++              case 'n':
++              case 'a':
++              case 'h':
++                      details->type = *signature;
++                      return signature + 1;
++              case '?':
++                      details->nullable = 1;
++              }
++      }
++      details->type = '\0';
++      return signature;
++}
++
++int
++arg_count_for_signature(const char *signature)
++{
++      int count = 0;
++      for(; *signature; ++signature) {
++              switch(*signature) {
++              case 'i':
++              case 'u':
++              case 'f':
++              case 's':
++              case 'o':
++              case 'n':
++              case 'a':
++              case 'h':
++                      ++count;
++              }
++      }
++      return count;
++}
++
++int
++wl_message_get_since(const struct wl_message *message)
++{
++      int since;
++
++      since = atoi(message->signature);
++
++      if (since == 0)
++              since = 1;
++
++      return since;
++}
++
++void
++wl_argument_from_va_list(const char *signature, union wl_argument *args,
++                       int count, va_list ap)
++{
++      int i;
++      const char *sig_iter;
++      struct argument_details arg;
++
++      sig_iter = signature;
++      for (i = 0; i < count; i++) {
++              sig_iter = get_next_argument(sig_iter, &arg);
++
++              switch(arg.type) {
++              case 'i':
++                      args[i].i = va_arg(ap, int32_t);
++                      break;
++              case 'u':
++                      args[i].u = va_arg(ap, uint32_t);
++                      break;
++              case 'f':
++                      args[i].f = va_arg(ap, wl_fixed_t);
++                      break;
++              case 's':
++                      args[i].s = va_arg(ap, const char *);
++                      break;
++              case 'o':
++                      args[i].o = va_arg(ap, struct wl_object *);
++                      break;
++              case 'n':
++                      args[i].o = va_arg(ap, struct wl_object *);
++                      break;
++              case 'a':
++                      args[i].a = va_arg(ap, struct wl_array *);
++                      break;
++              case 'h':
++                      args[i].h = va_arg(ap, int32_t);
++                      break;
++              case '\0':
++                      return;
++              }
++      }
++}
++
++static void
++wl_closure_clear_fds(struct wl_closure *closure)
++{
++      const char *signature = closure->message->signature;
++      struct argument_details arg;
++      int i;
++
++      for (i = 0; i < closure->count; i++) {
++              signature = get_next_argument(signature, &arg);
++              if (arg.type == 'h')
++                      closure->args[i].h = -1;
++      }
++}
++
++static struct wl_closure *
++wl_closure_init(const struct wl_message *message, uint32_t size,
++                int *num_arrays, union wl_argument *args)
++{
++      struct wl_closure *closure;
++      int count;
++
++      count = arg_count_for_signature(message->signature);
++      if (count > WL_CLOSURE_MAX_ARGS) {
++              wl_log("too many args (%d)\n", count);
++              errno = EINVAL;
++              return NULL;
++      }
++
++      if (size) {
++              *num_arrays = wl_message_count_arrays(message);
++              closure = zalloc(sizeof *closure + size +
++                               *num_arrays * sizeof(struct wl_array));
++      } else {
++              closure = zalloc(sizeof *closure);
++      }
++
++      if (!closure) {
++              errno = ENOMEM;
++              return NULL;
++      }
++
++      if (args)
++              memcpy(closure->args, args, count * sizeof *args);
++
++      closure->message = message;
++      closure->count = count;
++
++      /* Set these all to -1 so we can close any that have been
++       * set to a real value during wl_closure_destroy().
++       * We may have copied a bunch of fds into the closure with
++       * memcpy previously, but those are undup()d client fds
++       * that we would have replaced anyway.
++       */
++      wl_closure_clear_fds(closure);
++
++      return closure;
++}
++
++struct wl_closure *
++wl_closure_marshal(struct wl_object *sender, uint32_t opcode,
++                 union wl_argument *args,
++                 const struct wl_message *message)
++{
++      struct wl_closure *closure;
++      struct wl_object *object;
++      int i, count, fd, dup_fd;
++      const char *signature;
++      struct argument_details arg;
++
++      closure = wl_closure_init(message, 0, NULL, args);
++      if (closure == NULL)
++              return NULL;
++
++      count = closure->count;
++
++      signature = message->signature;
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++
++              switch (arg.type) {
++              case 'f':
++              case 'u':
++              case 'i':
++                      break;
++              case 's':
++                      if (!arg.nullable && args[i].s == NULL)
++                              goto err_null;
++                      break;
++              case 'o':
++                      if (!arg.nullable && args[i].o == NULL)
++                              goto err_null;
++                      break;
++              case 'n':
++                      object = args[i].o;
++                      if (object == NULL)
++                              goto err_null;
++
++                      closure->args[i].n = object ? object->id : 0;
++                      break;
++              case 'a':
++                      if (args[i].a == NULL)
++                              goto err_null;
++                      break;
++              case 'h':
++                      fd = args[i].h;
++                      dup_fd = wl_os_dupfd_cloexec(fd, 0);
++                      if (dup_fd < 0) {
++                              wl_closure_destroy(closure);
++                              wl_log("error marshalling arguments for %s: dup failed: %s\n",
++                                     message->name, strerror(errno));
++                              return NULL;
++                      }
++                      closure->args[i].h = dup_fd;
++                      break;
++              default:
++                      wl_abort("unhandled format code: '%c'\n", arg.type);
++                      break;
++              }
++      }
++
++      closure->sender_id = sender->id;
++      closure->opcode = opcode;
++
++      return closure;
++
++err_null:
++      wl_closure_destroy(closure);
++      wl_log("error marshalling arguments for %s (signature %s): "
++             "null value passed for arg %i\n", message->name,
++             message->signature, i);
++      errno = EINVAL;
++      return NULL;
++}
++
++struct wl_closure *
++wl_closure_vmarshal(struct wl_object *sender, uint32_t opcode, va_list ap,
++                  const struct wl_message *message)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++
++      wl_argument_from_va_list(message->signature, args,
++                               WL_CLOSURE_MAX_ARGS, ap);
++
++      return wl_closure_marshal(sender, opcode, args, message);
++}
++
++struct wl_closure *
++wl_connection_demarshal(struct wl_connection *connection,
++                      uint32_t size,
++                      struct wl_map *objects,
++                      const struct wl_message *message)
++{
++      uint32_t *p, *next, *end, length, length_in_u32, id;
++      int fd;
++      char *s;
++      int i, count, num_arrays;
++      const char *signature;
++      struct argument_details arg;
++      struct wl_closure *closure;
++      struct wl_array *array_extra;
++
++      /* Space for sender_id and opcode */
++      if (size < 2 * sizeof *p) {
++              wl_log("message too short, invalid header\n");
++              wl_connection_consume(connection, size);
++              errno = EINVAL;
++              return NULL;
++      }
++
++      closure = wl_closure_init(message, size, &num_arrays, NULL);
++      if (closure == NULL) {
++              wl_connection_consume(connection, size);
++              return NULL;
++      }
++
++      count = closure->count;
++
++      array_extra = closure->extra;
++      p = (uint32_t *)(closure->extra + num_arrays);
++      end = p + size / sizeof *p;
++
++      wl_connection_copy(connection, p, size);
++      closure->sender_id = *p++;
++      closure->opcode = *p++ & 0x0000ffff;
++
++      signature = message->signature;
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++
++              if (arg.type != 'h' && p + 1 > end) {
++                      wl_log("message too short, "
++                             "object (%d), message %s(%s)\n",
++                             closure->sender_id, message->name,
++                             message->signature);
++                      errno = EINVAL;
++                      goto err;
++              }
++
++              switch (arg.type) {
++              case 'u':
++                      closure->args[i].u = *p++;
++                      break;
++              case 'i':
++                      closure->args[i].i = *p++;
++                      break;
++              case 'f':
++                      closure->args[i].f = *p++;
++                      break;
++              case 's':
++                      length = *p++;
++
++                      if (length == 0 && !arg.nullable) {
++                              wl_log("NULL string received on non-nullable "
++                                     "type, message %s(%s)\n", message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++                      if (length == 0) {
++                              closure->args[i].s = NULL;
++                              break;
++                      }
++
++                      length_in_u32 = div_roundup(length, sizeof *p);
++                      if ((uint32_t) (end - p) < length_in_u32) {
++                              wl_log("message too short, "
++                                     "object (%d), message %s(%s)\n",
++                                     closure->sender_id, message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++                      next = p + length_in_u32;
++
++                      s = (char *) p;
++
++                      if (length > 0 && s[length - 1] != '\0') {
++                              wl_log("string not nul-terminated, "
++                                     "message %s(%s)\n",
++                                     message->name, message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++
++                      closure->args[i].s = s;
++                      p = next;
++                      break;
++              case 'o':
++                      id = *p++;
++                      closure->args[i].n = id;
++
++                      if (id == 0 && !arg.nullable) {
++                              wl_log("NULL object received on non-nullable "
++                                     "type, message %s(%s)\n", message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++                      break;
++              case 'n':
++                      id = *p++;
++                      closure->args[i].n = id;
++
++                      if (id == 0) {
++                              wl_log("NULL new ID received on non-nullable "
++                                     "type, message %s(%s)\n", message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++
++                      if (wl_map_reserve_new(objects, id) < 0) {
++                              if (errno == EINVAL) {
++                                      wl_log("not a valid new object id (%u), "
++                                             "message %s(%s)\n", id,
++                                             message->name,
++                                             message->signature);
++                              }
++                              goto err;
++                      }
++
++                      break;
++              case 'a':
++                      length = *p++;
++
++                      length_in_u32 = div_roundup(length, sizeof *p);
++                      if ((uint32_t) (end - p) < length_in_u32) {
++                              wl_log("message too short, "
++                                     "object (%d), message %s(%s)\n",
++                                     closure->sender_id, message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++                      next = p + length_in_u32;
++
++                      array_extra->size = length;
++                      array_extra->alloc = 0;
++                      array_extra->data = p;
++
++                      closure->args[i].a = array_extra++;
++                      p = next;
++                      break;
++              case 'h':
++                      if (connection->fds_in.tail == connection->fds_in.head) {
++                              wl_log("file descriptor expected, "
++                                     "object (%d), message %s(%s)\n",
++                                     closure->sender_id, message->name,
++                                     message->signature);
++                              errno = EINVAL;
++                              goto err;
++                      }
++
++                      ring_buffer_copy(&connection->fds_in, &fd, sizeof fd);
++                      connection->fds_in.tail += sizeof fd;
++                      closure->args[i].h = fd;
++                      break;
++              default:
++                      wl_abort("unknown type\n");
++                      break;
++              }
++      }
++
++      wl_connection_consume(connection, size);
++
++      return closure;
++
++ err:
++      wl_closure_destroy(closure);
++      wl_connection_consume(connection, size);
++
++      return NULL;
++}
++
++bool
++wl_object_is_zombie(struct wl_map *map, uint32_t id)
++{
++      uint32_t flags;
++
++      /* Zombie objects only exist on the client side. */
++      if (map->side == WL_MAP_SERVER_SIDE)
++              return false;
++
++      /* Zombie objects can only have been created by the client. */
++      if (id >= WL_SERVER_ID_START)
++              return false;
++
++      flags = wl_map_lookup_flags(map, id);
++      return !!(flags & WL_MAP_ENTRY_ZOMBIE);
++}
++
++int
++wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects)
++{
++      struct wl_object *object;
++      const struct wl_message *message;
++      const char *signature;
++      struct argument_details arg;
++      int i, count;
++      uint32_t id;
++
++      message = closure->message;
++      signature = message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'o':
++                      id = closure->args[i].n;
++                      closure->args[i].o = NULL;
++
++                      object = wl_map_lookup(objects, id);
++                      if (wl_object_is_zombie(objects, id)) {
++                              /* references object we've already
++                               * destroyed client side */
++                              object = NULL;
++                      } else if (object == NULL && id != 0) {
++                              wl_log("unknown object (%u), message %s(%s)\n",
++                                     id, message->name, message->signature);
++                              errno = EINVAL;
++                              return -1;
++                      }
++
++                      if (object != NULL && message->types[i] != NULL &&
++                          !wl_interface_equal((object)->interface,
++                                              message->types[i])) {
++                              wl_log("invalid object (%u), type (%s), "
++                                     "message %s(%s)\n",
++                                     id, (object)->interface->name,
++                                     message->name, message->signature);
++                              errno = EINVAL;
++                              return -1;
++                      }
++                      closure->args[i].o = object;
++              }
++      }
++
++      return 0;
++}
++
++static void
++convert_arguments_to_ffi(const char *signature, uint32_t flags,
++                       union wl_argument *args,
++                       int count, ffi_type **ffi_types, void** ffi_args)
++{
++      int i;
++      const char *sig_iter;
++      struct argument_details arg;
++
++      sig_iter = signature;
++      for (i = 0; i < count; i++) {
++              sig_iter = get_next_argument(sig_iter, &arg);
++
++              switch(arg.type) {
++              case 'i':
++                      ffi_types[i] = &ffi_type_sint32;
++                      ffi_args[i] = &args[i].i;
++                      break;
++              case 'u':
++                      ffi_types[i] = &ffi_type_uint32;
++                      ffi_args[i] = &args[i].u;
++                      break;
++              case 'f':
++                      ffi_types[i] = &ffi_type_sint32;
++                      ffi_args[i] = &args[i].f;
++                      break;
++              case 's':
++                      ffi_types[i] = &ffi_type_pointer;
++                      ffi_args[i] = &args[i].s;
++                      break;
++              case 'o':
++                      ffi_types[i] = &ffi_type_pointer;
++                      ffi_args[i] = &args[i].o;
++                      break;
++              case 'n':
++                      if (flags & WL_CLOSURE_INVOKE_CLIENT) {
++                              ffi_types[i] = &ffi_type_pointer;
++                              ffi_args[i] = &args[i].o;
++                      } else {
++                              ffi_types[i] = &ffi_type_uint32;
++                              ffi_args[i] = &args[i].n;
++                      }
++                      break;
++              case 'a':
++                      ffi_types[i] = &ffi_type_pointer;
++                      ffi_args[i] = &args[i].a;
++                      break;
++              case 'h':
++                      ffi_types[i] = &ffi_type_sint32;
++                      ffi_args[i] = &args[i].h;
++                      break;
++              default:
++                      wl_abort("unknown type\n");
++                      break;
++              }
++      }
++}
++
++void
++wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
++                struct wl_object *target, uint32_t opcode, void *data)
++{
++      int count;
++      ffi_cif cif;
++      ffi_type *ffi_types[WL_CLOSURE_MAX_ARGS + 2];
++      void * ffi_args[WL_CLOSURE_MAX_ARGS + 2];
++      void (* const *implementation)(void);
++
++      count = arg_count_for_signature(closure->message->signature);
++
++      ffi_types[0] = &ffi_type_pointer;
++      ffi_args[0] = &data;
++      ffi_types[1] = &ffi_type_pointer;
++      ffi_args[1] = &target;
++
++      convert_arguments_to_ffi(closure->message->signature, flags, closure->args,
++                               count, ffi_types + 2, ffi_args + 2);
++
++      ffi_prep_cif(&cif, FFI_DEFAULT_ABI,
++                   count + 2, &ffi_type_void, ffi_types);
++
++      implementation = target->implementation;
++      if (!implementation[opcode]) {
++              wl_abort("listener function for opcode %u of %s is NULL\n",
++                       opcode, target->interface->name);
++      }
++      ffi_call(&cif, implementation[opcode], NULL, ffi_args);
++
++      wl_closure_clear_fds(closure);
++}
++
++void
++wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
++                  struct wl_object *target, uint32_t opcode)
++{
++      dispatcher(target->implementation, target, opcode, closure->message,
++                 closure->args);
++
++      wl_closure_clear_fds(closure);
++}
++
++static int
++copy_fds_to_connection(struct wl_closure *closure,
++                     struct wl_connection *connection)
++{
++      const struct wl_message *message = closure->message;
++      uint32_t i, count;
++      struct argument_details arg;
++      const char *signature = message->signature;
++      int fd;
++
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              if (arg.type != 'h')
++                      continue;
++
++              fd = closure->args[i].h;
++              if (wl_connection_put_fd(connection, fd)) {
++                      wl_log("request could not be marshaled: "
++                             "can't send file descriptor\n");
++                      return -1;
++              }
++              closure->args[i].h = -1;
++      }
++
++      return 0;
++}
++
++
++static uint32_t
++buffer_size_for_closure(struct wl_closure *closure)
++{
++      const struct wl_message *message = closure->message;
++      int i, count;
++      struct argument_details arg;
++      const char *signature;
++      uint32_t size, buffer_size = 0;
++
++      signature = message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++
++              switch (arg.type) {
++              case 'h':
++                      break;
++              case 'u':
++              case 'i':
++              case 'f':
++              case 'o':
++              case 'n':
++                      buffer_size++;
++                      break;
++              case 's':
++                      if (closure->args[i].s == NULL) {
++                              buffer_size++;
++                              break;
++                      }
++
++                      size = strlen(closure->args[i].s) + 1;
++                      buffer_size += 1 + div_roundup(size, sizeof(uint32_t));
++                      break;
++              case 'a':
++                      if (closure->args[i].a == NULL) {
++                              buffer_size++;
++                              break;
++                      }
++
++                      size = closure->args[i].a->size;
++                      buffer_size += (1 + div_roundup(size, sizeof(uint32_t)));
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      return buffer_size + 2;
++}
++
++static int
++serialize_closure(struct wl_closure *closure, uint32_t *buffer,
++                size_t buffer_count)
++{
++      const struct wl_message *message = closure->message;
++      unsigned int i, count, size;
++      uint32_t *p, *end;
++      struct argument_details arg;
++      const char *signature;
++
++      if (buffer_count < 2)
++              goto overflow;
++
++      p = buffer + 2;
++      end = buffer + buffer_count;
++
++      signature = message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++
++              if (arg.type == 'h')
++                      continue;
++
++              if (p + 1 > end)
++                      goto overflow;
++
++              switch (arg.type) {
++              case 'u':
++                      *p++ = closure->args[i].u;
++                      break;
++              case 'i':
++                      *p++ = closure->args[i].i;
++                      break;
++              case 'f':
++                      *p++ = closure->args[i].f;
++                      break;
++              case 'o':
++                      *p++ = closure->args[i].o ? closure->args[i].o->id : 0;
++                      break;
++              case 'n':
++                      *p++ = closure->args[i].n;
++                      break;
++              case 's':
++                      if (closure->args[i].s == NULL) {
++                              *p++ = 0;
++                              break;
++                      }
++
++                      size = strlen(closure->args[i].s) + 1;
++                      *p++ = size;
++
++                      if (p + div_roundup(size, sizeof *p) > end)
++                              goto overflow;
++
++                      memcpy(p, closure->args[i].s, size);
++                      p += div_roundup(size, sizeof *p);
++                      break;
++              case 'a':
++                      if (closure->args[i].a == NULL) {
++                              *p++ = 0;
++                              break;
++                      }
++
++                      size = closure->args[i].a->size;
++                      *p++ = size;
++
++                      if (p + div_roundup(size, sizeof *p) > end)
++                              goto overflow;
++
++                      memcpy(p, closure->args[i].a->data, size);
++                      p += div_roundup(size, sizeof *p);
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      size = (p - buffer) * sizeof *p;
++
++      buffer[0] = closure->sender_id;
++      buffer[1] = size << 16 | (closure->opcode & 0x0000ffff);
++
++      return size;
++
++overflow:
++      errno = ERANGE;
++      return -1;
++}
++
++int
++wl_closure_send(struct wl_closure *closure, struct wl_connection *connection)
++{
++      int size;
++      uint32_t buffer_size;
++      uint32_t *buffer;
++      int result;
++
++      if (copy_fds_to_connection(closure, connection))
++              return -1;
++
++      buffer_size = buffer_size_for_closure(closure);
++      buffer = zalloc(buffer_size * sizeof buffer[0]);
++      if (buffer == NULL)
++              return -1;
++
++      size = serialize_closure(closure, buffer, buffer_size);
++      if (size < 0) {
++              free(buffer);
++              return -1;
++      }
++
++      result = wl_connection_write(connection, buffer, size);
++      free(buffer);
++
++      return result;
++}
++
++int
++wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection)
++{
++      int size;
++      uint32_t buffer_size;
++      uint32_t *buffer;
++      int result;
++
++      if (copy_fds_to_connection(closure, connection))
++              return -1;
++
++      buffer_size = buffer_size_for_closure(closure);
++      buffer = malloc(buffer_size * sizeof buffer[0]);
++      if (buffer == NULL)
++              return -1;
++
++      size = serialize_closure(closure, buffer, buffer_size);
++      if (size < 0) {
++              free(buffer);
++              return -1;
++      }
++
++      result = wl_connection_queue(connection, buffer, size);
++      free(buffer);
++
++      return result;
++}
++
++void
++wl_closure_print(struct wl_closure *closure, struct wl_object *target,
++               int send, int discarded, uint32_t (*n_parse)(union wl_argument *arg))
++{
++      int i;
++      struct argument_details arg;
++      const char *signature = closure->message->signature;
++      struct timespec tp;
++      unsigned int time;
++      uint32_t nval;
++      FILE *f;
++      char *buffer;
++      size_t buffer_length;
++
++      f = open_memstream(&buffer, &buffer_length);
++      if (f == NULL)
++              return;
++
++      clock_gettime(CLOCK_REALTIME, &tp);
++      time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
++
++      fprintf(f, "[%7u.%03u] %s%s%s@%u.%s(",
++              time / 1000, time % 1000,
++              discarded ? "discarded " : "",
++              send ? " -> " : "",
++              target->interface->name, target->id,
++              closure->message->name);
++
++      for (i = 0; i < closure->count; i++) {
++              signature = get_next_argument(signature, &arg);
++              if (i > 0)
++                      fprintf(f, ", ");
++
++              switch (arg.type) {
++              case 'u':
++                      fprintf(f, "%u", closure->args[i].u);
++                      break;
++              case 'i':
++                      fprintf(f, "%d", closure->args[i].i);
++                      break;
++              case 'f':
++                      /* The magic number 390625 is 1e8 / 256 */
++                      if (closure->args[i].f >= 0) {
++                              fprintf(f, "%d.%08d",
++                                      closure->args[i].f / 256,
++                                      390625 * (closure->args[i].f % 256));
++                      } else {
++
++                              fprintf(f, "-%d.%08d",
++                                      closure->args[i].f / -256,
++                                      -390625 * (closure->args[i].f % 256));
++                      }
++                      break;
++              case 's':
++                      if (closure->args[i].s)
++                              fprintf(f, "\"%s\"", closure->args[i].s);
++                      else
++                              fprintf(f, "nil");
++                      break;
++              case 'o':
++                      if (closure->args[i].o)
++                              fprintf(f, "%s@%u",
++                                      closure->args[i].o->interface->name,
++                                      closure->args[i].o->id);
++                      else
++                              fprintf(f, "nil");
++                      break;
++              case 'n':
++                      if (n_parse)
++                              nval = n_parse(&closure->args[i]);
++                      else
++                              nval = closure->args[i].n;
++
++                      fprintf(f, "new id %s@",
++                              (closure->message->types[i]) ?
++                               closure->message->types[i]->name :
++                                "[unknown]");
++                      if (nval != 0)
++                              fprintf(f, "%u", nval);
++                      else
++                              fprintf(f, "nil");
++                      break;
++              case 'a':
++                      fprintf(f, "array[%zu]", closure->args[i].a->size);
++                      break;
++              case 'h':
++                      fprintf(f, "fd %d", closure->args[i].h);
++                      break;
++              }
++      }
++
++      fprintf(f, ")\n");
++
++      if (fclose(f) == 0) {
++              fprintf(stderr, "%s", buffer);
++              free(buffer);
++      }
++}
++
++static int
++wl_closure_close_fds(struct wl_closure *closure)
++{
++      int i;
++      struct argument_details arg;
++      const char *signature = closure->message->signature;
++
++      for (i = 0; i < closure->count; i++) {
++              signature = get_next_argument(signature, &arg);
++              if (arg.type == 'h' && closure->args[i].h != -1)
++                      close(closure->args[i].h);
++      }
++
++      return 0;
++}
++
++void
++wl_closure_destroy(struct wl_closure *closure)
++{
++      /* wl_closure_destroy has free() semantics */
++      if (!closure)
++              return;
++
++      wl_closure_close_fds(closure);
++      free(closure);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..abebb157fce94b6766c803b6990f7352380ac79c
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,45 @@@
++#!/usr/bin/env python3
++
++"""
++Simple C data embedder
++
++License: MIT
++
++Copyright (c) 2020 Simon Ser
++
++Permission is hereby granted, free of charge, to any person obtaining a copy
++of this software and associated documentation files (the "Software"), to deal
++in the Software without restriction, including without limitation the rights
++to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
++copies of the Software, and to permit persons to whom the Software is
++furnished to do so, subject to the following conditions:
++
++The above copyright notice and this permission notice shall be included in all
++copies or substantial portions of the Software.
++
++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
++IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
++FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
++AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
++LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
++OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++SOFTWARE.
++"""
++
++import sys
++
++if len(sys.argv) != 3:
++    print('usage: ' + sys.argv[0] + ' <filename> <ident>', file=sys.stderr)
++    sys.exit(1)
++
++filename = sys.argv[1]
++ident = sys.argv[2]
++
++with open(filename, 'rb') as f:
++    buf = f.read()
++
++print('static const char ' + ident + '[] = {\n\t', end='')
++for i in range(len(buf)):
++    ch = buf[i:i+1]
++    print('0x' + ch.hex() + ', ', end='')
++print('\n};')
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..37cf95d3f2118086298f279e00208e94e786a5ee
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1090 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <errno.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include <string.h>
++#include <fcntl.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <sys/epoll.h>
++#include <sys/signalfd.h>
++#include <sys/timerfd.h>
++#include <unistd.h>
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server-core.h"
++#include "wayland-os.h"
++
++/** \cond INTERNAL */
++
++#define TIMER_REMOVED -2
++
++struct wl_event_loop;
++struct wl_event_source_interface;
++struct wl_event_source_timer;
++
++struct wl_event_source {
++      struct wl_event_source_interface *interface;
++      struct wl_event_loop *loop;
++      struct wl_list link;
++      void *data;
++      int fd;
++};
++
++struct wl_timer_heap {
++      struct wl_event_source base;
++      /* pointers to the user-visible event sources */
++      struct wl_event_source_timer **data;
++      int space, active, count;
++};
++
++struct wl_event_loop {
++      int epoll_fd;
++      struct wl_list check_list;
++      struct wl_list idle_list;
++      struct wl_list destroy_list;
++
++      struct wl_signal destroy_signal;
++
++      struct wl_timer_heap timers;
++};
++
++struct wl_event_source_interface {
++      int (*dispatch)(struct wl_event_source *source,
++                      struct epoll_event *ep);
++};
++
++
++struct wl_event_source_fd {
++      struct wl_event_source base;
++      wl_event_loop_fd_func_t func;
++      int fd;
++};
++
++/** \endcond */
++
++static int
++wl_event_source_fd_dispatch(struct wl_event_source *source,
++                          struct epoll_event *ep)
++{
++      struct wl_event_source_fd *fd_source = (struct wl_event_source_fd *) source;
++      uint32_t mask;
++
++      mask = 0;
++      if (ep->events & EPOLLIN)
++              mask |= WL_EVENT_READABLE;
++      if (ep->events & EPOLLOUT)
++              mask |= WL_EVENT_WRITABLE;
++      if (ep->events & EPOLLHUP)
++              mask |= WL_EVENT_HANGUP;
++      if (ep->events & EPOLLERR)
++              mask |= WL_EVENT_ERROR;
++
++      return fd_source->func(fd_source->fd, mask, source->data);
++}
++
++struct wl_event_source_interface fd_source_interface = {
++      wl_event_source_fd_dispatch,
++};
++
++static struct wl_event_source *
++add_source(struct wl_event_loop *loop,
++         struct wl_event_source *source, uint32_t mask, void *data)
++{
++      struct epoll_event ep;
++
++      if (source->fd < 0) {
++              free(source);
++              return NULL;
++      }
++
++      source->loop = loop;
++      source->data = data;
++      wl_list_init(&source->link);
++
++      memset(&ep, 0, sizeof ep);
++      if (mask & WL_EVENT_READABLE)
++              ep.events |= EPOLLIN;
++      if (mask & WL_EVENT_WRITABLE)
++              ep.events |= EPOLLOUT;
++      ep.data.ptr = source;
++
++      if (epoll_ctl(loop->epoll_fd, EPOLL_CTL_ADD, source->fd, &ep) < 0) {
++              close(source->fd);
++              free(source);
++              return NULL;
++      }
++
++      return source;
++}
++
++/** Create a file descriptor event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param fd The file descriptor to watch.
++ * \param mask A bitwise-or of which events to watch for: \c WL_EVENT_READABLE,
++ * \c WL_EVENT_WRITABLE.
++ * \param func The file descriptor dispatch function.
++ * \param data User data.
++ * \return A new file descriptor event source.
++ *
++ * The given file descriptor is initially watched for the events given in
++ * \c mask. This can be changed as needed with wl_event_source_fd_update().
++ *
++ * If it is possible that program execution causes the file descriptor to be
++ * read while leaving the data in a buffer without actually processing it,
++ * it may be necessary to register the file descriptor source to be re-checked,
++ * see wl_event_source_check(). This will ensure that the dispatch function
++ * gets called even if the file descriptor is not readable or writable
++ * anymore. This is especially useful with IPC libraries that automatically
++ * buffer incoming data, possibly as a side-effect of other operations.
++ *
++ * \sa wl_event_loop_fd_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_fd(struct wl_event_loop *loop,
++                   int fd, uint32_t mask,
++                   wl_event_loop_fd_func_t func,
++                   void *data)
++{
++      struct wl_event_source_fd *source;
++
++      source = zalloc(sizeof *source);
++      if (source == NULL)
++              return NULL;
++
++      source->base.interface = &fd_source_interface;
++      source->base.fd = wl_os_dupfd_cloexec(fd, 0);
++      source->func = func;
++      source->fd = fd;
++
++      return add_source(loop, &source->base, mask, data);
++}
++
++/** Update a file descriptor source's event mask
++ *
++ * \param source The file descriptor event source to update.
++ * \param mask The new mask, a bitwise-or of: \c WL_EVENT_READABLE,
++ * \c WL_EVENT_WRITABLE.
++ * \return 0 on success, -1 on failure.
++ *
++ * This changes which events, readable and/or writable, cause the dispatch
++ * callback to be called on.
++ *
++ * File descriptors are usually writable to begin with, so they do not need to
++ * be polled for writable until a write actually fails. When a write fails,
++ * the event mask can be changed to poll for readable and writable, delivering
++ * a dispatch callback when it is possible to write more. Once all data has
++ * been written, the mask can be changed to poll only for readable to avoid
++ * busy-looping on dispatch.
++ *
++ * \sa wl_event_loop_add_fd()
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask)
++{
++      struct wl_event_loop *loop = source->loop;
++      struct epoll_event ep;
++
++      memset(&ep, 0, sizeof ep);
++      if (mask & WL_EVENT_READABLE)
++              ep.events |= EPOLLIN;
++      if (mask & WL_EVENT_WRITABLE)
++              ep.events |= EPOLLOUT;
++      ep.data.ptr = source;
++
++      return epoll_ctl(loop->epoll_fd, EPOLL_CTL_MOD, source->fd, &ep);
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_timer {
++      struct wl_event_source base;
++      wl_event_loop_timer_func_t func;
++      struct wl_event_source_timer *next_due;
++      struct timespec deadline;
++      int heap_idx;
++};
++
++static int
++noop_dispatch(struct wl_event_source *source,
++            struct epoll_event *ep) {
++      return 0;
++}
++
++struct wl_event_source_interface timer_heap_source_interface = {
++      noop_dispatch,
++};
++
++static bool
++time_lt(struct timespec ta, struct timespec tb)
++{
++      if (ta.tv_sec != tb.tv_sec) {
++              return ta.tv_sec < tb.tv_sec;
++      }
++      return ta.tv_nsec < tb.tv_nsec;
++}
++
++static int
++set_timer(int timerfd, struct timespec deadline) {
++      struct itimerspec its;
++
++      its.it_interval.tv_sec = 0;
++      its.it_interval.tv_nsec = 0;
++      its.it_value = deadline;
++      return timerfd_settime(timerfd, TFD_TIMER_ABSTIME, &its, NULL);
++}
++
++static int
++clear_timer(int timerfd)
++{
++      struct itimerspec its;
++
++      its.it_interval.tv_sec = 0;
++      its.it_interval.tv_nsec = 0;
++      its.it_value.tv_sec = 0;
++      its.it_value.tv_nsec = 0;
++      return timerfd_settime(timerfd, 0, &its, NULL);
++}
++
++static void
++wl_timer_heap_init(struct wl_timer_heap *timers, struct wl_event_loop *loop)
++{
++      timers->base.fd = -1;
++      timers->base.data = NULL;
++      wl_list_init(&timers->base.link);
++      timers->base.interface = &timer_heap_source_interface;
++      timers->base.loop = loop;
++
++      loop->timers.data = NULL;
++      loop->timers.active = 0;
++      loop->timers.space = 0;
++      loop->timers.count = 0;
++}
++
++static void
++wl_timer_heap_release(struct wl_timer_heap *timers)
++{
++      if (timers->base.fd != -1) {
++              close(timers->base.fd);
++      }
++      free(timers->data);
++}
++
++static int
++wl_timer_heap_ensure_timerfd(struct wl_timer_heap *timers)
++{
++      struct epoll_event ep;
++      int timer_fd;
++
++      if (timers->base.fd != -1)
++              return 0;
++
++      memset(&ep, 0, sizeof ep);
++      ep.events = EPOLLIN;
++      ep.data.ptr = timers;
++
++      timer_fd = timerfd_create(CLOCK_MONOTONIC,
++                                TFD_CLOEXEC | TFD_NONBLOCK);
++      if (timer_fd < 0)
++              return -1;
++
++      if (epoll_ctl(timers->base.loop->epoll_fd,
++                    EPOLL_CTL_ADD, timer_fd, &ep) < 0) {
++              close(timer_fd);
++              return -1;
++      }
++
++      timers->base.fd = timer_fd;
++      return 0;
++}
++
++static int
++wl_timer_heap_reserve(struct wl_timer_heap *timers)
++{
++      struct wl_event_source_timer **n;
++      int new_space;
++
++      if (timers->count + 1 > timers->space) {
++              new_space = timers->space >= 8 ? timers->space * 2 : 8;
++              n = realloc(timers->data, (size_t)new_space * sizeof(*n));
++              if (!n) {
++                      wl_log("Allocation failure when expanding timer list\n");
++                      return -1;
++              }
++              timers->data = n;
++              timers->space = new_space;
++      }
++
++      timers->count++;
++      return 0;
++}
++
++static void
++wl_timer_heap_unreserve(struct wl_timer_heap *timers)
++{
++      struct wl_event_source_timer **n;
++
++      timers->count--;
++
++      if (timers->space >= 16 && timers->space >= 4 * timers->count) {
++              n = realloc(timers->data, (size_t)timers->space / 2 * sizeof(*n));
++              if (!n) {
++                      wl_log("Reallocation failure when shrinking timer list\n");
++                      return;
++              }
++              timers->data = n;
++              timers->space = timers->space / 2;
++      }
++}
++
++static int
++heap_set(struct wl_event_source_timer **data,
++       struct wl_event_source_timer *a,
++       int idx)
++{
++      int tmp;
++
++      tmp = a->heap_idx;
++      a->heap_idx = idx;
++      data[a->heap_idx] = a;
++
++      return tmp;
++}
++
++static void
++heap_sift_down(struct wl_event_source_timer **data,
++             int num_active,
++             struct wl_event_source_timer *source)
++{
++      struct wl_event_source_timer *child, *other_child;
++      int cursor_idx;
++      struct timespec key;
++
++      cursor_idx = source->heap_idx;
++      key = source->deadline;
++      while (1) {
++              int lchild_idx = cursor_idx * 2 + 1;
++
++              if (lchild_idx >= num_active) {
++                      break;
++              }
++
++              child = data[lchild_idx];
++              if (lchild_idx + 1 < num_active) {
++                      other_child = data[lchild_idx + 1];
++                      if (time_lt(other_child->deadline, child->deadline))
++                              child = other_child;
++              }
++
++              if (time_lt(child->deadline, key))
++                      cursor_idx = heap_set(data, child, cursor_idx);
++              else
++                      break;
++      }
++
++      heap_set(data, source, cursor_idx);
++}
++
++static void
++heap_sift_up(struct wl_event_source_timer **data,
++           struct wl_event_source_timer *source)
++{
++      int cursor_idx;
++      struct timespec key;
++
++      cursor_idx = source->heap_idx;
++      key = source->deadline;
++      while (cursor_idx > 0) {
++              struct wl_event_source_timer *parent =
++                      data[(cursor_idx - 1) / 2];
++
++              if (time_lt(key, parent->deadline))
++                      cursor_idx = heap_set(data, parent, cursor_idx);
++              else
++                      break;
++      }
++      heap_set(data, source, cursor_idx);
++}
++
++/* requires timer be armed */
++static void
++wl_timer_heap_disarm(struct wl_timer_heap *timers,
++                   struct wl_event_source_timer *source)
++{
++      struct wl_event_source_timer *last_end_evt;
++      int old_source_idx;
++
++      assert(source->heap_idx >= 0);
++
++      old_source_idx = source->heap_idx;
++      source->heap_idx = -1;
++      source->deadline.tv_sec = 0;
++      source->deadline.tv_nsec = 0;
++
++      last_end_evt = timers->data[timers->active - 1];
++      timers->data[timers->active - 1] = NULL;
++      timers->active--;
++
++      if (old_source_idx == timers->active)
++              return;
++
++      timers->data[old_source_idx] = last_end_evt;
++      last_end_evt->heap_idx = old_source_idx;
++
++      /* Move the displaced (active) element to its proper place.
++       * Only one of sift-down and sift-up will have any effect */
++      heap_sift_down(timers->data, timers->active, last_end_evt);
++      heap_sift_up(timers->data, last_end_evt);
++}
++
++/* requires timer be disarmed */
++static void
++wl_timer_heap_arm(struct wl_timer_heap *timers,
++                struct wl_event_source_timer *source,
++                struct timespec deadline)
++{
++      assert(source->heap_idx == -1);
++
++      source->deadline = deadline;
++      timers->data[timers->active] = source;
++      source->heap_idx = timers->active;
++      timers->active++;
++      heap_sift_up(timers->data, source);
++}
++
++
++static int
++wl_timer_heap_dispatch(struct wl_timer_heap *timers)
++{
++      struct timespec now;
++      struct wl_event_source_timer *root;
++      struct wl_event_source_timer *list_cursor = NULL, *list_tail = NULL;
++
++      clock_gettime(CLOCK_MONOTONIC, &now);
++
++      while (timers->active > 0) {
++              root = timers->data[0];
++              if (time_lt(now, root->deadline))
++                      break;
++
++              wl_timer_heap_disarm(timers, root);
++
++              if (list_cursor == NULL)
++                      list_cursor = root;
++              else
++                      list_tail->next_due = root;
++              list_tail = root;
++      }
++      if (list_tail)
++              list_tail->next_due = NULL;
++
++      if (timers->active > 0) {
++              if (set_timer(timers->base.fd, timers->data[0]->deadline) < 0)
++                      return -1;
++      } else {
++              if (clear_timer(timers->base.fd) < 0)
++                      return -1;
++      }
++
++      /* Execute precisely the functions for events before `now`, in order.
++       * Because wl_event_loop_dispatch ignores return codes, do the same
++       * here as well */
++      for (; list_cursor; list_cursor = list_cursor->next_due) {
++              if (list_cursor->base.fd != TIMER_REMOVED)
++                      list_cursor->func(list_cursor->base.data);
++      }
++
++      return 0;
++}
++
++static int
++wl_event_source_timer_dispatch(struct wl_event_source *source,
++                             struct epoll_event *ep)
++{
++      struct wl_event_source_timer *timer;
++
++      timer = wl_container_of(source, timer, base);
++      return timer->func(timer->base.data);
++}
++
++struct wl_event_source_interface timer_source_interface = {
++      wl_event_source_timer_dispatch,
++};
++
++/** \endcond */
++
++/** Create a timer event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param func The timer dispatch function.
++ * \param data User data.
++ * \return A new timer event source.
++ *
++ * The timer is initially disarmed. It needs to be armed with a call to
++ * wl_event_source_timer_update() before it can trigger a dispatch call.
++ *
++ * \sa wl_event_loop_timer_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_timer(struct wl_event_loop *loop,
++                      wl_event_loop_timer_func_t func,
++                      void *data)
++{
++      struct wl_event_source_timer *source;
++
++      if (wl_timer_heap_ensure_timerfd(&loop->timers) < 0)
++              return NULL;
++
++      source = zalloc(sizeof *source);
++      if (source == NULL)
++              return NULL;
++
++      source->base.interface = &timer_source_interface;
++      source->base.fd = -1;
++      source->func = func;
++      source->base.loop = loop;
++      source->base.data = data;
++      wl_list_init(&source->base.link);
++      source->next_due = NULL;
++      source->deadline.tv_sec = 0;
++      source->deadline.tv_nsec = 0;
++      source->heap_idx = -1;
++
++      if (wl_timer_heap_reserve(&loop->timers) < 0) {
++              free(source);
++              return NULL;
++      }
++
++      return &source->base;
++}
++
++/** Arm or disarm a timer
++ *
++ * \param source The timer event source to modify.
++ * \param ms_delay The timeout in milliseconds.
++ * \return 0 on success, -1 on failure.
++ *
++ * If the timeout is zero, the timer is disarmed.
++ *
++ * If the timeout is non-zero, the timer is set to expire after the given
++ * timeout in milliseconds. When the timer expires, the dispatch function
++ * set with wl_event_loop_add_timer() is called once from
++ * wl_event_loop_dispatch(). If another dispatch is desired after another
++ * expiry, wl_event_source_timer_update() needs to be called again.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_timer_update(struct wl_event_source *source, int ms_delay)
++{
++      struct wl_event_source_timer *tsource =
++              wl_container_of(source, tsource, base);
++      struct wl_timer_heap *timers = &tsource->base.loop->timers;
++
++      if (ms_delay > 0) {
++              struct timespec deadline;
++
++              clock_gettime(CLOCK_MONOTONIC, &deadline);
++
++              deadline.tv_nsec += (ms_delay % 1000) * 1000000L;
++              deadline.tv_sec += ms_delay / 1000;
++              if (deadline.tv_nsec >= 1000000000L) {
++                      deadline.tv_nsec -= 1000000000L;
++                      deadline.tv_sec += 1;
++              }
++
++              if (tsource->heap_idx == -1) {
++                      wl_timer_heap_arm(timers, tsource, deadline);
++              } else if (time_lt(deadline, tsource->deadline)) {
++                      tsource->deadline = deadline;
++                      heap_sift_up(timers->data, tsource);
++              } else {
++                      tsource->deadline = deadline;
++                      heap_sift_down(timers->data, timers->active, tsource);
++              }
++
++              if (tsource->heap_idx == 0) {
++                      /* Only update the timerfd if the new deadline is
++                       * the earliest */
++                      if (set_timer(timers->base.fd, deadline) < 0)
++                              return -1;
++              }
++      } else {
++              if (tsource->heap_idx == -1)
++                      return 0;
++              wl_timer_heap_disarm(timers, tsource);
++
++              if (timers->active == 0) {
++                      /* Only update the timerfd if this was the last
++                       * active timer */
++                      if (clear_timer(timers->base.fd) < 0)
++                              return -1;
++              }
++      }
++
++      return 0;
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_signal {
++      struct wl_event_source base;
++      int signal_number;
++      wl_event_loop_signal_func_t func;
++};
++
++/** \endcond */
++
++static int
++wl_event_source_signal_dispatch(struct wl_event_source *source,
++                              struct epoll_event *ep)
++{
++      struct wl_event_source_signal *signal_source =
++              (struct wl_event_source_signal *) source;
++      struct signalfd_siginfo signal_info;
++      int len;
++
++      len = read(source->fd, &signal_info, sizeof signal_info);
++      if (!(len == -1 && errno == EAGAIN) && len != sizeof signal_info)
++              /* Is there anything we can do here?  Will this ever happen? */
++              wl_log("signalfd read error: %s\n", strerror(errno));
++
++      return signal_source->func(signal_source->signal_number,
++                                 signal_source->base.data);
++}
++
++struct wl_event_source_interface signal_source_interface = {
++      wl_event_source_signal_dispatch,
++};
++
++/** Create a POSIX signal event source
++ *
++ * \param loop The event loop that will process the new source.
++ * \param signal_number Number of the signal to watch for.
++ * \param func The signal dispatch function.
++ * \param data User data.
++ * \return A new signal event source.
++ *
++ * This function blocks the normal delivery of the given signal in the calling
++ * thread, and creates a "watch" for it. Signal delivery no longer happens
++ * asynchronously, but by wl_event_loop_dispatch() calling the dispatch
++ * callback function \c func.
++ *
++ * It is the caller's responsibility to ensure that all other threads have
++ * also blocked the signal.
++ *
++ * \sa wl_event_loop_signal_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_signal(struct wl_event_loop *loop,
++                       int signal_number,
++                       wl_event_loop_signal_func_t func,
++                       void *data)
++{
++      struct wl_event_source_signal *source;
++      sigset_t mask;
++
++      source = zalloc(sizeof *source);
++      if (source == NULL)
++              return NULL;
++
++      source->base.interface = &signal_source_interface;
++      source->signal_number = signal_number;
++
++      sigemptyset(&mask);
++      sigaddset(&mask, signal_number);
++      source->base.fd = signalfd(-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
++      sigprocmask(SIG_BLOCK, &mask, NULL);
++
++      source->func = func;
++
++      return add_source(loop, &source->base, WL_EVENT_READABLE, data);
++}
++
++/** \cond INTERNAL */
++
++struct wl_event_source_idle {
++      struct wl_event_source base;
++      wl_event_loop_idle_func_t func;
++};
++
++/** \endcond */
++
++struct wl_event_source_interface idle_source_interface = {
++      NULL,
++};
++
++/** Create an idle task
++ *
++ * \param loop The event loop that will process the new task.
++ * \param func The idle task dispatch function.
++ * \param data User data.
++ * \return A new idle task (an event source).
++ *
++ * Idle tasks are dispatched before wl_event_loop_dispatch() goes to sleep.
++ * See wl_event_loop_dispatch() for more details.
++ *
++ * Idle tasks fire once, and are automatically destroyed right after the
++ * callback function has been called.
++ *
++ * An idle task can be cancelled before the callback has been called by
++ * wl_event_source_remove(). Calling wl_event_source_remove() after or from
++ * within the callback results in undefined behaviour.
++ *
++ * \sa wl_event_loop_idle_func_t
++ * \memberof wl_event_source
++ */
++WL_EXPORT struct wl_event_source *
++wl_event_loop_add_idle(struct wl_event_loop *loop,
++                     wl_event_loop_idle_func_t func,
++                     void *data)
++{
++      struct wl_event_source_idle *source;
++
++      source = zalloc(sizeof *source);
++      if (source == NULL)
++              return NULL;
++
++      source->base.interface = &idle_source_interface;
++      source->base.loop = loop;
++      source->base.fd = -1;
++
++      source->func = func;
++      source->base.data = data;
++
++      wl_list_insert(loop->idle_list.prev, &source->base.link);
++
++      return &source->base;
++}
++
++/** Mark event source to be re-checked
++ *
++ * \param source The event source to be re-checked.
++ *
++ * This function permanently marks the event source to be re-checked after
++ * the normal dispatch of sources in wl_event_loop_dispatch(). Re-checking
++ * will keep iterating over all such event sources until the dispatch
++ * function for them all returns zero.
++ *
++ * Re-checking is used on sources that may become ready to dispatch as a
++ * side-effect of dispatching themselves or other event sources, including idle
++ * sources. Re-checking ensures all the incoming events have been fully drained
++ * before wl_event_loop_dispatch() returns.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT void
++wl_event_source_check(struct wl_event_source *source)
++{
++      wl_list_insert(source->loop->check_list.prev, &source->link);
++}
++
++/** Remove an event source from its event loop
++ *
++ * \param source The event source to be removed.
++ * \return Zero.
++ *
++ * The event source is removed from the event loop it was created for,
++ * and is effectively destroyed. This invalidates \c source .
++ * The dispatch function of the source will no longer be called through this
++ * source.
++ *
++ * \memberof wl_event_source
++ */
++WL_EXPORT int
++wl_event_source_remove(struct wl_event_source *source)
++{
++      struct wl_event_loop *loop = source->loop;
++
++      /* We need to explicitly remove the fd, since closing the fd
++       * isn't enough in case we've dup'ed the fd. */
++      if (source->fd >= 0) {
++              epoll_ctl(loop->epoll_fd, EPOLL_CTL_DEL, source->fd, NULL);
++              close(source->fd);
++              source->fd = -1;
++      }
++
++      if (source->interface == &timer_source_interface &&
++          source->fd != TIMER_REMOVED) {
++              /* Disarm the timer (and the loop's timerfd, if necessary),
++               * before removing its space in the loop timer heap */
++              wl_event_source_timer_update(source, 0);
++              wl_timer_heap_unreserve(&loop->timers);
++              /* Set the fd field to to indicate that the timer should NOT
++               * be dispatched in `wl_event_loop_dispatch` */
++              source->fd = TIMER_REMOVED;
++      }
++
++      wl_list_remove(&source->link);
++      wl_list_insert(&loop->destroy_list, &source->link);
++
++      return 0;
++}
++
++static void
++wl_event_loop_process_destroy_list(struct wl_event_loop *loop)
++{
++      struct wl_event_source *source, *next;
++
++      wl_list_for_each_safe(source, next, &loop->destroy_list, link)
++              free(source);
++
++      wl_list_init(&loop->destroy_list);
++}
++
++/** Create a new event loop context
++ *
++ * \return A new event loop context object.
++ *
++ * This creates a new event loop context. Initially this context is empty.
++ * Event sources need to be explicitly added to it.
++ *
++ * Normally the event loop is run by calling wl_event_loop_dispatch() in
++ * a loop until the program terminates. Alternatively, an event loop can be
++ * embedded in another event loop by its file descriptor, see
++ * wl_event_loop_get_fd().
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT struct wl_event_loop *
++wl_event_loop_create(void)
++{
++      struct wl_event_loop *loop;
++
++      loop = zalloc(sizeof *loop);
++      if (loop == NULL)
++              return NULL;
++
++      loop->epoll_fd = wl_os_epoll_create_cloexec();
++      if (loop->epoll_fd < 0) {
++              free(loop);
++              return NULL;
++      }
++      wl_list_init(&loop->check_list);
++      wl_list_init(&loop->idle_list);
++      wl_list_init(&loop->destroy_list);
++
++      wl_signal_init(&loop->destroy_signal);
++
++      wl_timer_heap_init(&loop->timers, loop);
++
++      return loop;
++}
++
++/** Destroy an event loop context
++ *
++ * \param loop The event loop to be destroyed.
++ *
++ * This emits the event loop destroy signal, closes the event loop file
++ * descriptor, and frees \c loop.
++ *
++ * If the event loop has existing sources, those cannot be safely removed
++ * afterwards. Therefore one must call wl_event_source_remove() on all
++ * event sources before destroying the event loop context.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_destroy(struct wl_event_loop *loop)
++{
++      wl_signal_emit(&loop->destroy_signal, loop);
++
++      wl_event_loop_process_destroy_list(loop);
++      wl_timer_heap_release(&loop->timers);
++      close(loop->epoll_fd);
++      free(loop);
++}
++
++static bool
++post_dispatch_check(struct wl_event_loop *loop)
++{
++      struct epoll_event ep;
++      struct wl_event_source *source, *next;
++      bool needs_recheck = false;
++
++      ep.events = 0;
++      wl_list_for_each_safe(source, next, &loop->check_list, link) {
++              int dispatch_result;
++
++              dispatch_result = source->interface->dispatch(source, &ep);
++              if (dispatch_result < 0) {
++                      wl_log("Source dispatch function returned negative value!\n");
++                      wl_log("This would previously accidentally suppress a follow-up dispatch\n");
++              }
++              needs_recheck |= dispatch_result != 0;
++      }
++
++      return needs_recheck;
++}
++
++/** Dispatch the idle sources
++ *
++ * \param loop The event loop whose idle sources are dispatched.
++ *
++ * \sa wl_event_loop_add_idle()
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_dispatch_idle(struct wl_event_loop *loop)
++{
++      struct wl_event_source_idle *source;
++
++      while (!wl_list_empty(&loop->idle_list)) {
++              source = wl_container_of(loop->idle_list.next,
++                                       source, base.link);
++              source->func(source->base.data);
++              wl_event_source_remove(&source->base);
++      }
++}
++
++/** Wait for events and dispatch them
++ *
++ * \param loop The event loop whose sources to wait for.
++ * \param timeout The polling timeout in milliseconds.
++ * \return 0 for success, -1 for polling (or timer update) error.
++ *
++ * All the associated event sources are polled. This function blocks until
++ * any event source delivers an event (idle sources excluded), or the timeout
++ * expires. A timeout of -1 disables the timeout, causing the function to block
++ * indefinitely. A timeout of zero causes the poll to always return immediately.
++ *
++ * All idle sources are dispatched before blocking. An idle source is destroyed
++ * when it is dispatched. After blocking, all other ready sources are
++ * dispatched. Then, idle sources are dispatched again, in case the dispatched
++ * events created idle sources. Finally, all sources marked with
++ * wl_event_source_check() are dispatched in a loop until their dispatch
++ * functions all return zero.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT int
++wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout)
++{
++      struct epoll_event ep[32];
++      struct wl_event_source *source;
++      int i, count;
++      bool has_timers = false;
++
++      wl_event_loop_dispatch_idle(loop);
++
++      count = epoll_wait(loop->epoll_fd, ep, ARRAY_LENGTH(ep), timeout);
++      if (count < 0)
++              return -1;
++
++      for (i = 0; i < count; i++) {
++              source = ep[i].data.ptr;
++              if (source == &loop->timers.base)
++                      has_timers = true;
++      }
++
++      if (has_timers) {
++              /* Dispatch timer sources before non-timer sources, so that
++               * the non-timer sources can not cancel (by calling
++               * `wl_event_source_timer_update`) the dispatching of the timers
++               * (Note that timer sources also can't cancel pending non-timer
++               * sources, since epoll_wait has already been called) */
++              if (wl_timer_heap_dispatch(&loop->timers) < 0)
++                      return -1;
++      }
++
++      for (i = 0; i < count; i++) {
++              source = ep[i].data.ptr;
++              if (source->fd != -1)
++                      source->interface->dispatch(source, &ep[i]);
++      }
++
++      wl_event_loop_process_destroy_list(loop);
++
++      wl_event_loop_dispatch_idle(loop);
++
++      while (post_dispatch_check(loop));
++
++      return 0;
++}
++
++/** Get the event loop file descriptor
++ *
++ * \param loop The event loop context.
++ * \return The aggregate file descriptor.
++ *
++ * This function returns the aggregate file descriptor, that represents all
++ * the event sources (idle sources excluded) associated with the given event
++ * loop context. When any event source makes an event available, it will be
++ * reflected in the aggregate file descriptor.
++ *
++ * When the aggregate file descriptor delivers an event, one can call
++ * wl_event_loop_dispatch() on the event loop context to dispatch all the
++ * available events.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT int
++wl_event_loop_get_fd(struct wl_event_loop *loop)
++{
++      return loop->epoll_fd;
++}
++
++/** Register a destroy listener for an event loop context
++ *
++ * \param loop The event loop context whose destruction to listen for.
++ * \param listener The listener with the callback to be called.
++ *
++ * \sa wl_listener
++ * \memberof wl_event_loop
++ */
++WL_EXPORT void
++wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
++                                 struct wl_listener *listener)
++{
++      wl_signal_add(&loop->destroy_signal, listener);
++}
++
++/** Get the listener struct for the specified callback
++ *
++ * \param loop The event loop context to inspect.
++ * \param notify The destroy callback to find.
++ * \return The wl_listener registered to the event loop context with
++ * the given callback pointer.
++ *
++ * \memberof wl_event_loop
++ */
++WL_EXPORT struct wl_listener *
++wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
++                                 wl_notify_func_t notify)
++{
++      return wl_signal_get(&loop->destroy_signal, notify);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a8a1d2ba979411a09fd754ef9b8ddf44a6f74653
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,277 @@@
++if not (get_option('scanner') or get_option('libraries'))
++      error('Either -Dscanner=true or -Dlibraries=true is required')
++endif
++
++wayland_version_h = configuration_data()
++wayland_version_h.set('WAYLAND_VERSION', meson.project_version())
++wayland_version_h.set('WAYLAND_VERSION_MAJOR', wayland_version[0].to_int())
++wayland_version_h.set('WAYLAND_VERSION_MINOR', wayland_version[1].to_int())
++wayland_version_h.set('WAYLAND_VERSION_MICRO', wayland_version[2].to_int())
++configure_file(
++      input: 'wayland-version.h.in',
++      output: 'wayland-version.h',
++      configuration: wayland_version_h,
++      install: get_option('libraries'),
++      install_dir: join_paths(get_option('prefix'), get_option('includedir'))
++)
++
++
++wayland_util = static_library(
++      'wayland-util',
++      sources: 'wayland-util.c'
++)
++
++wayland_util_dep = declare_dependency(
++      link_with: wayland_util,
++      include_directories: include_directories('.')
++)
++
++if get_option('scanner')
++      # wayland-scanner
++
++      scanner_deps = [ dependency('expat') ]
++      scanner_args = [ '-include', 'config.h' ]
++
++      if get_option('dtd_validation')
++              scanner_deps += dependency('libxml-2.0')
++              scanner_args += '-DHAVE_LIBXML=1'
++      endif
++
++      prog_embed = find_program('embed.py', native: true)
++
++      embed_dtd = custom_target(
++              'wayland.dtd.h',
++              input: '../protocol/wayland.dtd',
++              output: 'wayland.dtd.h',
++              command: [ prog_embed, '@INPUT@', 'wayland_dtd' ],
++              capture: true
++      )
++
++      wayland_scanner_sources = [ 'scanner.c', embed_dtd ]
++      wayland_scanner_includes = [ root_inc, protocol_inc ]
++
++      wayland_scanner = executable(
++              'wayland-scanner',
++              wayland_scanner_sources,
++              c_args: scanner_args,
++              include_directories: wayland_scanner_includes,
++              dependencies: [ scanner_deps, wayland_util_dep, ],
++              install: true
++      )
++
++      pkgconfig.generate(
++              name: 'Wayland Scanner',
++              description: 'Wayland scanner',
++              version: meson.project_version(),
++              variables: [
++                      'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++                      'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name()),
++                      'bindir=' + join_paths('${prefix}', get_option('bindir')),
++                      'wayland_scanner=${bindir}/wayland-scanner'
++              ],
++              filebase: 'wayland-scanner'
++      )
++
++      if meson.can_run_host_binaries()
++              meson.override_find_program('wayland-scanner', wayland_scanner)
++      endif
++endif
++
++if meson.is_cross_build() or not get_option('scanner')
++      scanner_dep = dependency('wayland-scanner', native: true, version: meson.project_version())
++      wayland_scanner_for_build = find_program(scanner_dep.get_variable(pkgconfig: 'wayland_scanner'))
++else
++      wayland_scanner_for_build = wayland_scanner
++endif
++
++if get_option('libraries')
++      # wayland libraries
++
++      mathlib_dep = cc.find_library('m', required: false)
++      threads_dep = dependency('threads', required: false)
++
++      wayland_private = static_library(
++              'wayland-private',
++              sources: [
++                      'connection.c',
++                      'wayland-os.c'
++              ],
++              dependencies: [ epoll_dep, ffi_dep, rt_dep ]
++      )
++
++      wayland_private_dep = declare_dependency(
++              link_with: wayland_private,
++              include_directories: include_directories('.')
++      )
++
++      generated_headers = [
++              {
++                      'scanner_args': ['server-header'],
++                      'output': 'wayland-server-protocol.h',
++                      'install': true,
++              },
++              {
++                      'scanner_args': ['server-header', '-c'],
++                      'output': 'wayland-server-protocol-core.h',
++                      'install': false,
++              },
++              {
++                      'scanner_args': ['client-header'],
++                      'output': 'wayland-client-protocol.h',
++                      'install': true,
++              },
++              {
++                      'scanner_args': ['client-header', '-c'],
++                      'output': 'wayland-client-protocol-core.h',
++                      'install': false,
++              },
++      ]
++
++      foreach gen: generated_headers
++              scanner_args = gen['scanner_args']
++              output_file = gen['output']
++              install_file = gen['install']
++              install_dir = join_paths(get_option('prefix'), get_option('includedir'))
++              target_name = output_file.underscorify()
++
++              target = custom_target(
++                      target_name,
++                      command: [
++                              wayland_scanner_for_build, '-s', scanner_args,
++                              '@INPUT@', '@OUTPUT@'
++                      ],
++                      input: wayland_protocol_xml,
++                      output: output_file,
++                      install: install_file,
++                      install_dir: install_dir
++              )
++
++              set_variable(target_name, target)
++      endforeach
++
++      wayland_protocol_c = custom_target(
++              'protocol source',
++              command: [
++                      wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@'
++              ],
++              input: wayland_protocol_xml,
++              output: 'wayland-protocol.c'
++      )
++
++      if wayland_version[0] != '1'
++              # The versioning used for the shared libraries assumes that the major
++              # version of Wayland as a whole will increase to 2 if and only if there
++              # is an ABI break, at which point we should probably bump the SONAME of
++              # all libraries to .so.2. For more details see
++              # https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/177
++              error('We probably need to bump the SONAME of libwayland-server and -client')
++      endif
++
++      wayland_server = library(
++              'wayland-server',
++              sources: [
++                      wayland_server_protocol_core_h,
++                      wayland_server_protocol_h,
++                      wayland_protocol_c,
++                      'wayland-server.c',
++                      'wayland-shm.c',
++                      'event-loop.c'
++              ],
++              # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++              # libwayland-server.so.0.x.y.
++              version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++              dependencies: [
++                      epoll_dep,
++                      ffi_dep,
++                      wayland_private_dep,
++                      wayland_util_dep,
++                      mathlib_dep,
++                      threads_dep,
++                      rt_dep
++              ],
++              include_directories: root_inc,
++              install: true
++      )
++
++      wayland_server_dep = declare_dependency(
++              link_with: wayland_server,
++              include_directories: [ root_inc, include_directories('.') ],
++              dependencies: [ epoll_dep, ffi_dep, mathlib_dep, threads_dep ],
++              sources: [
++                      wayland_server_protocol_core_h,
++                      wayland_server_protocol_h
++              ]
++      )
++
++      pkgconfig.generate(
++              wayland_server,
++              name: 'Wayland Server',
++              description: 'Server side implementation of the Wayland protocol',
++              version: meson.project_version(),
++              filebase: 'wayland-server',
++              variables: [
++                      'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++                      'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
++              ]
++      )
++
++      if meson.version().version_compare('>= 0.54.0')
++              meson.override_dependency('wayland-server', wayland_server_dep)
++      endif
++
++      wayland_client = library(
++              'wayland-client',
++              sources: [
++                      wayland_client_protocol_core_h,
++                      wayland_client_protocol_h,
++                      wayland_protocol_c,
++                      'wayland-client.c'
++              ],
++              # To avoid an unnecessary SONAME bump, wayland 1.x.y produces
++              # libwayland-client.so.0.x.y.
++              version: '.'.join(['0', wayland_version[1], wayland_version[2]]),
++              dependencies: [
++                      epoll_dep,
++                      ffi_dep,
++                      wayland_private_dep,
++                      wayland_util_dep,
++                      mathlib_dep,
++                      threads_dep
++              ],
++              include_directories: root_inc,
++              install: true
++      )
++
++      pkgconfig.generate(
++              wayland_client,
++              name: 'Wayland Client',
++              description: 'Wayland client side library',
++              version: meson.project_version(),
++              filebase: 'wayland-client',
++              variables: [
++                      'datarootdir=' + join_paths('${prefix}', get_option('datadir')),
++                      'pkgdatadir=' + join_paths('${datarootdir}', meson.project_name())
++              ]
++      )
++
++      wayland_client_dep = declare_dependency(
++              link_with: wayland_client,
++              include_directories: [ root_inc, include_directories('.') ],
++              sources: [
++                      wayland_client_protocol_core_h,
++                      wayland_client_protocol_h
++              ]
++      )
++
++      if meson.version().version_compare('>= 0.54.0')
++              meson.override_dependency('wayland-client', wayland_client_dep)
++      endif
++
++      install_headers([
++              'wayland-util.h',
++              'wayland-server.h',
++              'wayland-server-core.h',
++              'wayland-client.h',
++              'wayland-client-core.h',
++      ])
++endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..da8adea4588346aaf7b988f9b8211b815bffccbd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2083 @@@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2015 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-version.h"
++
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <errno.h>
++#include <ctype.h>
++#include <getopt.h>
++#include <limits.h>
++#include <unistd.h>
++
++#if HAVE_LIBXML
++#include <libxml/parser.h>
++
++/* Embedded wayland.dtd file */
++/* static const char wayland_dtd[]; wayland.dtd */
++#include "wayland.dtd.h"
++#endif
++
++/* Expat must be included after libxml as both want to declare XMLCALL; see
++ * the Git commit that 'git blame' for this comment points to for more. */
++#include <expat.h>
++
++#include "wayland-util.h"
++
++#define PROGRAM_NAME "wayland-scanner"
++
++enum side {
++      CLIENT,
++      SERVER,
++};
++
++enum visibility {
++      PRIVATE,
++      PUBLIC,
++};
++
++static int
++usage(int ret)
++{
++      fprintf(stderr, "usage: %s [OPTION] [client-header|server-header|private-code|public-code]"
++              " [input_file output_file]\n", PROGRAM_NAME);
++      fprintf(stderr, "\n");
++      fprintf(stderr, "Converts XML protocol descriptions supplied on "
++                      "stdin or input file to client\n"
++                      "headers, server headers, or protocol marshalling code.\n\n"
++                      "Use \"public-code\" only if the marshalling code will be public - "
++                      "aka DSO will export it while other components will be using it.\n"
++                      "Using \"private-code\" is strongly recommended.\n\n");
++      fprintf(stderr, "options:\n");
++      fprintf(stderr, "    -h,  --help                  display this help and exit.\n"
++                      "    -v,  --version               print the wayland library version that\n"
++                      "                                 the scanner was built against.\n"
++                      "    -c,  --include-core-only     include the core version of the headers,\n"
++                      "                                 that is e.g. wayland-client-core.h instead\n"
++                      "                                 of wayland-client.h.\n"
++                      "    -s,  --strict                exit immediately with an error if DTD\n"
++                      "                                 verification fails.\n");
++      exit(ret);
++}
++
++static int
++scanner_version(int ret)
++{
++      fprintf(stderr, "%s %s\n", PROGRAM_NAME, WAYLAND_VERSION);
++      exit(ret);
++}
++
++static bool
++is_dtd_valid(FILE *input, const char *filename)
++{
++      bool rc = true;
++#if HAVE_LIBXML
++      xmlParserCtxtPtr ctx = NULL;
++      xmlDocPtr doc = NULL;
++      xmlDtdPtr dtd = NULL;
++      xmlValidCtxtPtr dtdctx;
++      xmlParserInputBufferPtr buffer;
++      int fd = fileno(input);
++
++      dtdctx = xmlNewValidCtxt();
++      ctx = xmlNewParserCtxt();
++      if (!ctx || !dtdctx)
++              abort();
++
++      buffer = xmlParserInputBufferCreateMem(wayland_dtd,
++                                             sizeof(wayland_dtd),
++                                             XML_CHAR_ENCODING_UTF8);
++      if (!buffer) {
++              fprintf(stderr, "Failed to init buffer for DTD.\n");
++              abort();
++      }
++
++      dtd = xmlIOParseDTD(NULL, buffer, XML_CHAR_ENCODING_UTF8);
++      if (!dtd) {
++              fprintf(stderr, "Failed to parse DTD.\n");
++              abort();
++      }
++
++      doc = xmlCtxtReadFd(ctx, fd, filename, NULL, 0);
++      if (!doc) {
++              fprintf(stderr, "Failed to read XML\n");
++              abort();
++      }
++
++      rc = xmlValidateDtd(dtdctx, doc, dtd);
++      xmlFreeDoc(doc);
++      xmlFreeParserCtxt(ctx);
++      xmlFreeDtd(dtd);
++      xmlFreeValidCtxt(dtdctx);
++      /* xmlIOParseDTD consumes buffer */
++
++      if (lseek(fd, 0, SEEK_SET) != 0) {
++              fprintf(stderr, "Failed to reset fd, output would be garbage.\n");
++              abort();
++      }
++#endif
++      return rc;
++}
++
++#define XML_BUFFER_SIZE 4096
++
++struct location {
++      const char *filename;
++      int line_number;
++};
++
++struct description {
++      char *summary;
++      char *text;
++};
++
++struct protocol {
++      char *name;
++      char *uppercase_name;
++      struct wl_list interface_list;
++      int type_index;
++      int null_run_length;
++      char *copyright;
++      struct description *description;
++      bool core_headers;
++};
++
++struct interface {
++      struct location loc;
++      char *name;
++      char *uppercase_name;
++      int version;
++      int since;
++      struct wl_list request_list;
++      struct wl_list event_list;
++      struct wl_list enumeration_list;
++      struct wl_list link;
++      struct description *description;
++};
++
++struct message {
++      struct location loc;
++      char *name;
++      char *uppercase_name;
++      struct wl_list arg_list;
++      struct wl_list link;
++      int arg_count;
++      int new_id_count;
++      int type_index;
++      int all_null;
++      int destructor;
++      int since;
++      struct description *description;
++};
++
++enum arg_type {
++      NEW_ID,
++      INT,
++      UNSIGNED,
++      FIXED,
++      STRING,
++      OBJECT,
++      ARRAY,
++      FD
++};
++
++struct arg {
++      char *name;
++      enum arg_type type;
++      int nullable;
++      char *interface_name;
++      struct wl_list link;
++      char *summary;
++      char *enumeration_name;
++};
++
++struct enumeration {
++      char *name;
++      char *uppercase_name;
++      struct wl_list entry_list;
++      struct wl_list link;
++      struct description *description;
++      bool bitfield;
++      int since;
++};
++
++struct entry {
++      char *name;
++      char *uppercase_name;
++      char *value;
++      char *summary;
++      int since;
++      struct wl_list link;
++      struct description *description;
++};
++
++struct parse_context {
++      struct location loc;
++      XML_Parser parser;
++      struct protocol *protocol;
++      struct interface *interface;
++      struct message *message;
++      struct enumeration *enumeration;
++      struct entry *entry;
++      struct description *description;
++      char character_data[8192];
++      unsigned int character_data_length;
++};
++
++enum identifier_role {
++      STANDALONE_IDENT,
++      TRAILING_IDENT
++};
++
++static void *
++fail_on_null(void *p)
++{
++      if (p == NULL) {
++              fprintf(stderr, "%s: out of memory\n", PROGRAM_NAME);
++              exit(EXIT_FAILURE);
++      }
++
++      return p;
++}
++
++static void *
++zalloc(size_t s)
++{
++      return calloc(s, 1);
++}
++
++static void *
++xzalloc(size_t s)
++{
++      return fail_on_null(zalloc(s));
++}
++
++static char *
++xstrdup(const char *s)
++{
++      return fail_on_null(strdup(s));
++}
++
++static char *
++uppercase_dup(const char *src)
++{
++      char *u;
++      int i;
++
++      u = xstrdup(src);
++      for (i = 0; u[i]; i++)
++              u[i] = toupper(u[i]);
++      u[i] = '\0';
++
++      return u;
++}
++
++static const char *indent(int n)
++{
++      const char *whitespace[] = {
++              "\t\t\t\t\t\t\t\t\t\t\t\t",
++              "\t\t\t\t\t\t\t\t\t\t\t\t ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t  ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t   ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t    ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t     ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t      ",
++              "\t\t\t\t\t\t\t\t\t\t\t\t       "
++      };
++
++      return whitespace[n % 8] + 12 - n / 8;
++}
++
++static void
++desc_dump(char *desc, const char *fmt, ...) WL_PRINTF(2, 3);
++
++static void
++desc_dump(char *desc, const char *fmt, ...)
++{
++      va_list ap;
++      char buf[128], hang;
++      int col, i, j, k, startcol, newlines;
++
++      va_start(ap, fmt);
++      vsnprintf(buf, sizeof buf, fmt, ap);
++      va_end(ap);
++
++      for (i = 0, col = 0; buf[i] != '*'; i++) {
++              if (buf[i] == '\t')
++                      col = (col + 8) & ~7;
++              else
++                      col++;
++      }
++
++      printf("%s", buf);
++
++      if (!desc) {
++              printf("(none)\n");
++              return;
++      }
++
++      startcol = col;
++      col += strlen(&buf[i]);
++      if (col - startcol > 2)
++              hang = '\t';
++      else
++              hang = ' ';
++
++      for (i = 0; desc[i]; ) {
++              k = i;
++              newlines = 0;
++              while (desc[i] && isspace(desc[i])) {
++                      if (desc[i] == '\n')
++                              newlines++;
++                      i++;
++              }
++              if (!desc[i])
++                      break;
++
++              j = i;
++              while (desc[i] && !isspace(desc[i]))
++                      i++;
++
++              if (newlines > 1)
++                      printf("\n%s*", indent(startcol));
++              if (newlines > 1 || col + i - j > 72) {
++                      printf("\n%s*%c", indent(startcol), hang);
++                      col = startcol;
++              }
++
++              if (col > startcol && k > 0)
++                      col += printf(" ");
++              col += printf("%.*s", i - j, &desc[j]);
++      }
++      putchar('\n');
++}
++
++static void __attribute__ ((noreturn))
++fail(struct location *loc, const char *msg, ...)
++{
++      va_list ap;
++
++      va_start(ap, msg);
++      fprintf(stderr, "%s:%d: error: ",
++              loc->filename, loc->line_number);
++      vfprintf(stderr, msg, ap);
++      fprintf(stderr, "\n");
++      va_end(ap);
++      exit(EXIT_FAILURE);
++}
++
++static void
++warn(struct location *loc, const char *msg, ...)
++{
++      va_list ap;
++
++      va_start(ap, msg);
++      fprintf(stderr, "%s:%d: warning: ",
++              loc->filename, loc->line_number);
++      vfprintf(stderr, msg, ap);
++      fprintf(stderr, "\n");
++      va_end(ap);
++}
++
++static bool
++is_nullable_type(struct arg *arg)
++{
++      switch (arg->type) {
++      /* Strings and objects are possibly nullable */
++      case STRING:
++      case OBJECT:
++              return true;
++      default:
++              return false;
++      }
++}
++
++static struct message *
++create_message(struct location loc, const char *name)
++{
++      struct message *message;
++
++      message = xzalloc(sizeof *message);
++      message->loc = loc;
++      message->name = xstrdup(name);
++      message->uppercase_name = uppercase_dup(name);
++      wl_list_init(&message->arg_list);
++
++      return message;
++}
++
++static void
++free_arg(struct arg *arg)
++{
++      free(arg->name);
++      free(arg->interface_name);
++      free(arg->summary);
++      free(arg->enumeration_name);
++      free(arg);
++}
++
++static struct arg *
++create_arg(const char *name)
++{
++      struct arg *arg;
++
++      arg = xzalloc(sizeof *arg);
++      arg->name = xstrdup(name);
++
++      return arg;
++}
++
++static bool
++set_arg_type(struct arg *arg, const char *type)
++{
++      if (strcmp(type, "int") == 0)
++              arg->type = INT;
++      else if (strcmp(type, "uint") == 0)
++              arg->type = UNSIGNED;
++      else if (strcmp(type, "fixed") == 0)
++              arg->type = FIXED;
++      else if (strcmp(type, "string") == 0)
++              arg->type = STRING;
++      else if (strcmp(type, "array") == 0)
++              arg->type = ARRAY;
++      else if (strcmp(type, "fd") == 0)
++              arg->type = FD;
++      else if (strcmp(type, "new_id") == 0)
++              arg->type = NEW_ID;
++      else if (strcmp(type, "object") == 0)
++              arg->type = OBJECT;
++      else
++              return false;
++
++      return true;
++}
++
++static void
++free_description(struct description *desc)
++{
++      if (!desc)
++              return;
++
++      free(desc->summary);
++      free(desc->text);
++
++      free(desc);
++}
++
++static void
++free_message(struct message *message)
++{
++      struct arg *a, *a_next;
++
++      free(message->name);
++      free(message->uppercase_name);
++      free_description(message->description);
++
++      wl_list_for_each_safe(a, a_next, &message->arg_list, link)
++              free_arg(a);
++
++      free(message);
++}
++
++static struct enumeration *
++create_enumeration(const char *name)
++{
++      struct enumeration *enumeration;
++
++      enumeration = xzalloc(sizeof *enumeration);
++      enumeration->name = xstrdup(name);
++      enumeration->uppercase_name = uppercase_dup(name);
++      enumeration->since = 1;
++
++      wl_list_init(&enumeration->entry_list);
++
++      return enumeration;
++}
++
++static struct entry *
++create_entry(const char *name, const char *value)
++{
++      struct entry *entry;
++
++      entry = xzalloc(sizeof *entry);
++      entry->name = xstrdup(name);
++      entry->uppercase_name = uppercase_dup(name);
++      entry->value = xstrdup(value);
++
++      return entry;
++}
++
++static void
++free_entry(struct entry *entry)
++{
++      free(entry->name);
++      free(entry->uppercase_name);
++      free(entry->value);
++      free(entry->summary);
++      free_description(entry->description);
++
++      free(entry);
++}
++
++static void
++free_enumeration(struct enumeration *enumeration)
++{
++      struct entry *e, *e_next;
++
++      free(enumeration->name);
++      free(enumeration->uppercase_name);
++      free_description(enumeration->description);
++
++      wl_list_for_each_safe(e, e_next, &enumeration->entry_list, link)
++              free_entry(e);
++
++      free(enumeration);
++}
++
++static struct interface *
++create_interface(struct location loc, const char *name, int version)
++{
++      struct interface *interface;
++
++      interface = xzalloc(sizeof *interface);
++      interface->loc = loc;
++      interface->name = xstrdup(name);
++      interface->uppercase_name = uppercase_dup(name);
++      interface->version = version;
++      interface->since = 1;
++      wl_list_init(&interface->request_list);
++      wl_list_init(&interface->event_list);
++      wl_list_init(&interface->enumeration_list);
++
++      return interface;
++}
++
++static void
++free_interface(struct interface *interface)
++{
++      struct message *m, *next_m;
++      struct enumeration *e, *next_e;
++
++      free(interface->name);
++      free(interface->uppercase_name);
++      free_description(interface->description);
++
++      wl_list_for_each_safe(m, next_m, &interface->request_list, link)
++              free_message(m);
++      wl_list_for_each_safe(m, next_m, &interface->event_list, link)
++              free_message(m);
++      wl_list_for_each_safe(e, next_e, &interface->enumeration_list, link)
++              free_enumeration(e);
++
++      free(interface);
++}
++
++/* Convert string to unsigned integer
++ *
++ * Parses a non-negative base-10 number from the given string.  If the
++ * specified string is blank, contains non-numerical characters, is out
++ * of range, or results in a negative number, -1 is returned to indicate
++ * an error.
++ *
++ * Upon error, this routine does not modify or set errno.
++ *
++ * Returns -1 on error, or a non-negative integer on success
++ */
++static int
++strtouint(const char *str)
++{
++      long int ret;
++      char *end;
++      int prev_errno = errno;
++
++      errno = 0;
++      ret = strtol(str, &end, 10);
++      if (errno != 0 || end == str || *end != '\0')
++              return -1;
++
++      /* check range */
++      if (ret < 0 || ret > INT_MAX) {
++              return -1;
++      }
++
++      errno = prev_errno;
++      return (int)ret;
++}
++
++/* Check that the provided string will produce valid "C" identifiers.
++ *
++ * If the string will form the prefix of an identifier in the
++ * generated C code, then it must match [_a-zA-Z][_0-9a-zA-Z]*.
++ *
++ * If the string will form the suffix of an identifier, then
++ * it must match [_0-9a-zA-Z]+.
++ *
++ * Unicode characters or escape sequences are not permitted,
++ * since not all C compilers support them.
++ *
++ * If the above conditions are not met, then fail()
++ */
++static void
++validate_identifier(struct location *loc,
++              const char *str,
++              enum identifier_role role)
++{
++      const char *scan;
++
++      if (!*str) {
++              fail(loc, "element name is empty");
++      }
++
++      for (scan = str; *scan; scan++) {
++              char c = *scan;
++
++              /* we do not use the locale-dependent `isalpha` */
++              bool is_alpha = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
++              bool is_digit = c >= '0' && c <= '9';
++              bool leading_char = (scan == str) && role == STANDALONE_IDENT;
++
++              if (is_alpha || c == '_' || (!leading_char && is_digit))
++                      continue;
++
++              if (role == TRAILING_IDENT)
++                      fail(loc,
++                           "'%s' is not a valid trailing identifier part", str);
++              else
++                      fail(loc,
++                           "'%s' is not a valid standalone identifier", str);
++      }
++}
++
++static int
++version_from_since(struct parse_context *ctx, const char *since)
++{
++      int version;
++
++      if (since != NULL) {
++              version = strtouint(since);
++              if (version == -1) {
++                      fail(&ctx->loc, "invalid integer (%s)\n", since);
++              } else if (version > ctx->interface->version) {
++                      fail(&ctx->loc, "since (%u) larger than version (%u)\n",
++                           version, ctx->interface->version);
++              }
++      } else {
++              version = 1;
++      }
++
++
++      return version;
++}
++
++static void
++start_element(void *data, const char *element_name, const char **atts)
++{
++      struct parse_context *ctx = data;
++      struct interface *interface;
++      struct message *message;
++      struct arg *arg;
++      struct enumeration *enumeration;
++      struct entry *entry;
++      struct description *description = NULL;
++      const char *name = NULL;
++      const char *type = NULL;
++      const char *interface_name = NULL;
++      const char *value = NULL;
++      const char *summary = NULL;
++      const char *since = NULL;
++      const char *allow_null = NULL;
++      const char *enumeration_name = NULL;
++      const char *bitfield = NULL;
++      int i, version = 0;
++
++      ctx->loc.line_number = XML_GetCurrentLineNumber(ctx->parser);
++      for (i = 0; atts[i]; i += 2) {
++              if (strcmp(atts[i], "name") == 0)
++                      name = atts[i + 1];
++              if (strcmp(atts[i], "version") == 0) {
++                      version = strtouint(atts[i + 1]);
++                      if (version == -1)
++                              fail(&ctx->loc, "wrong version (%s)", atts[i + 1]);
++              }
++              if (strcmp(atts[i], "type") == 0)
++                      type = atts[i + 1];
++              if (strcmp(atts[i], "value") == 0)
++                      value = atts[i + 1];
++              if (strcmp(atts[i], "interface") == 0)
++                      interface_name = atts[i + 1];
++              if (strcmp(atts[i], "summary") == 0)
++                      summary = atts[i + 1];
++              if (strcmp(atts[i], "since") == 0)
++                      since = atts[i + 1];
++              if (strcmp(atts[i], "allow-null") == 0)
++                      allow_null = atts[i + 1];
++              if (strcmp(atts[i], "enum") == 0)
++                      enumeration_name = atts[i + 1];
++              if (strcmp(atts[i], "bitfield") == 0)
++                      bitfield = atts[i + 1];
++      }
++
++      ctx->character_data_length = 0;
++      if (strcmp(element_name, "protocol") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no protocol name given");
++
++              validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++              ctx->protocol->name = xstrdup(name);
++              ctx->protocol->uppercase_name = uppercase_dup(name);
++      } else if (strcmp(element_name, "copyright") == 0) {
++
++      } else if (strcmp(element_name, "interface") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no interface name given");
++
++              if (version == 0)
++                      fail(&ctx->loc, "no interface version given");
++
++              validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++              interface = create_interface(ctx->loc, name, version);
++              ctx->interface = interface;
++              wl_list_insert(ctx->protocol->interface_list.prev,
++                             &interface->link);
++      } else if (strcmp(element_name, "request") == 0 ||
++                 strcmp(element_name, "event") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no request name given");
++
++              validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++              message = create_message(ctx->loc, name);
++
++              if (strcmp(element_name, "request") == 0)
++                      wl_list_insert(ctx->interface->request_list.prev,
++                                     &message->link);
++              else
++                      wl_list_insert(ctx->interface->event_list.prev,
++                                     &message->link);
++
++              if (type != NULL && strcmp(type, "destructor") == 0)
++                      message->destructor = 1;
++
++              version = version_from_since(ctx, since);
++
++              if (version < ctx->interface->since)
++                      warn(&ctx->loc, "since version not increasing\n");
++              ctx->interface->since = version;
++              message->since = version;
++
++              if (strcmp(name, "destroy") == 0 && !message->destructor)
++                      fail(&ctx->loc, "destroy request should be destructor type");
++
++              ctx->message = message;
++      } else if (strcmp(element_name, "arg") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no argument name given");
++
++              validate_identifier(&ctx->loc, name, STANDALONE_IDENT);
++              arg = create_arg(name);
++              if (!set_arg_type(arg, type))
++                      fail(&ctx->loc, "unknown type (%s)", type);
++
++              switch (arg->type) {
++              case NEW_ID:
++                      ctx->message->new_id_count++;
++                      /* fallthrough */
++              case OBJECT:
++                      if (interface_name) {
++                              validate_identifier(&ctx->loc,
++                                                  interface_name,
++                                                  STANDALONE_IDENT);
++                              arg->interface_name = xstrdup(interface_name);
++                      }
++                      break;
++              default:
++                      if (interface_name != NULL)
++                              fail(&ctx->loc, "interface attribute not allowed for type %s", type);
++                      break;
++              }
++
++              if (allow_null) {
++                      if (strcmp(allow_null, "true") == 0)
++                              arg->nullable = 1;
++                      else if (strcmp(allow_null, "false") != 0)
++                              fail(&ctx->loc,
++                                   "invalid value for allow-null attribute (%s)",
++                                   allow_null);
++
++                      if (!is_nullable_type(arg))
++                              fail(&ctx->loc,
++                                   "allow-null is only valid for objects, strings, and arrays");
++              }
++
++              if (enumeration_name == NULL || strcmp(enumeration_name, "") == 0)
++                      arg->enumeration_name = NULL;
++              else
++                      arg->enumeration_name = xstrdup(enumeration_name);
++
++              if (summary)
++                      arg->summary = xstrdup(summary);
++
++              wl_list_insert(ctx->message->arg_list.prev, &arg->link);
++              ctx->message->arg_count++;
++      } else if (strcmp(element_name, "enum") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no enum name given");
++
++              validate_identifier(&ctx->loc, name, TRAILING_IDENT);
++              enumeration = create_enumeration(name);
++
++              if (bitfield == NULL || strcmp(bitfield, "false") == 0)
++                      enumeration->bitfield = false;
++              else if (strcmp(bitfield, "true") == 0)
++                      enumeration->bitfield = true;
++              else
++                      fail(&ctx->loc,
++                           "invalid value (%s) for bitfield attribute (only true/false are accepted)",
++                           bitfield);
++
++              wl_list_insert(ctx->interface->enumeration_list.prev,
++                             &enumeration->link);
++
++              ctx->enumeration = enumeration;
++      } else if (strcmp(element_name, "entry") == 0) {
++              if (name == NULL)
++                      fail(&ctx->loc, "no entry name given");
++
++              validate_identifier(&ctx->loc, name, TRAILING_IDENT);
++              entry = create_entry(name, value);
++              version = version_from_since(ctx, since);
++
++              if (version < ctx->enumeration->since)
++                      warn(&ctx->loc, "since version not increasing\n");
++              ctx->enumeration->since = version;
++              entry->since = version;
++
++              if (summary)
++                      entry->summary = xstrdup(summary);
++              else
++                      entry->summary = NULL;
++              wl_list_insert(ctx->enumeration->entry_list.prev,
++                             &entry->link);
++              ctx->entry = entry;
++      } else if (strcmp(element_name, "description") == 0) {
++              if (summary == NULL)
++                      fail(&ctx->loc, "description without summary");
++
++              description = xzalloc(sizeof *description);
++              description->summary = xstrdup(summary);
++
++              if (ctx->message)
++                      ctx->message->description = description;
++              else if (ctx->entry)
++                      ctx->entry->description = description;
++              else if (ctx->enumeration)
++                      ctx->enumeration->description = description;
++              else if (ctx->interface)
++                      ctx->interface->description = description;
++              else
++                      ctx->protocol->description = description;
++              ctx->description = description;
++      }
++}
++
++static struct enumeration *
++find_enumeration(struct protocol *protocol,
++               struct interface *interface,
++               char *enum_attribute)
++{
++      struct interface *i;
++      struct enumeration *e;
++      char *enum_name;
++      uint32_t idx = 0, j;
++
++      for (j = 0; j + 1 < strlen(enum_attribute); j++) {
++              if (enum_attribute[j] == '.') {
++                      idx = j;
++              }
++      }
++
++      if (idx > 0) {
++              enum_name = enum_attribute + idx + 1;
++
++              wl_list_for_each(i, &protocol->interface_list, link)
++                      if (strncmp(i->name, enum_attribute, idx) == 0)
++                              wl_list_for_each(e, &i->enumeration_list, link)
++                                      if (strcmp(e->name, enum_name) == 0)
++                                              return e;
++      } else if (interface) {
++              enum_name = enum_attribute;
++
++              wl_list_for_each(e, &interface->enumeration_list, link)
++                      if (strcmp(e->name, enum_name) == 0)
++                              return e;
++      }
++
++      return NULL;
++}
++
++static void
++verify_arguments(struct parse_context *ctx,
++               struct interface *interface,
++               struct wl_list *messages,
++               struct wl_list *enumerations)
++{
++      struct message *m;
++      wl_list_for_each(m, messages, link) {
++              struct arg *a;
++              wl_list_for_each(a, &m->arg_list, link) {
++                      struct enumeration *e;
++
++                      if (!a->enumeration_name)
++                              continue;
++
++
++                      e = find_enumeration(ctx->protocol, interface,
++                                           a->enumeration_name);
++
++                      switch (a->type) {
++                      case INT:
++                              if (e && e->bitfield)
++                                      fail(&ctx->loc,
++                                           "bitfield-style enum must only be referenced by uint");
++                              break;
++                      case UNSIGNED:
++                              break;
++                      default:
++                              fail(&ctx->loc,
++                                   "enumeration-style argument has wrong type");
++                      }
++              }
++      }
++
++}
++
++#ifndef HAVE_STRNDUP
++char *
++strndup(const char *s, size_t size)
++{
++      char *r = malloc(size + 1);
++      strncpy(r, s, size);
++      r[size] = '\0';
++      return r;
++}
++#endif
++
++static void
++end_element(void *data, const XML_Char *name)
++{
++      struct parse_context *ctx = data;
++
++      if (strcmp(name, "copyright") == 0) {
++              ctx->protocol->copyright =
++                      strndup(ctx->character_data,
++                              ctx->character_data_length);
++      } else if (strcmp(name, "description") == 0) {
++              ctx->description->text =
++                      strndup(ctx->character_data,
++                              ctx->character_data_length);
++              ctx->description = NULL;
++      } else if (strcmp(name, "request") == 0 ||
++                 strcmp(name, "event") == 0) {
++              ctx->message = NULL;
++      } else if (strcmp(name, "enum") == 0) {
++              if (wl_list_empty(&ctx->enumeration->entry_list)) {
++                      fail(&ctx->loc, "enumeration %s was empty",
++                           ctx->enumeration->name);
++              }
++              ctx->enumeration = NULL;
++      } else if (strcmp(name, "entry") == 0) {
++              ctx->entry = NULL;
++      } else if (strcmp(name, "protocol") == 0) {
++              struct interface *i;
++
++              wl_list_for_each(i, &ctx->protocol->interface_list, link) {
++                      verify_arguments(ctx, i, &i->request_list, &i->enumeration_list);
++                      verify_arguments(ctx, i, &i->event_list, &i->enumeration_list);
++              }
++      }
++}
++
++static void
++character_data(void *data, const XML_Char *s, int len)
++{
++      struct parse_context *ctx = data;
++
++      if (ctx->character_data_length + len > sizeof (ctx->character_data)) {
++              fprintf(stderr, "too much character data");
++              exit(EXIT_FAILURE);
++          }
++
++      memcpy(ctx->character_data + ctx->character_data_length, s, len);
++      ctx->character_data_length += len;
++}
++
++static void
++format_text_to_comment(const char *text, bool standalone_comment)
++{
++      int bol = 1, start = 0, i, length;
++      bool comment_started = !standalone_comment;
++
++      length = strlen(text);
++      for (i = 0; i <= length; i++) {
++              if (bol && (text[i] == ' ' || text[i] == '\t')) {
++                      continue;
++              } else if (bol) {
++                      bol = 0;
++                      start = i;
++              }
++              if (text[i] == '\n' ||
++                  (text[i] == '\0' && !(start == i))) {
++                      printf("%s%s%.*s\n",
++                             comment_started ? " *" : "/*",
++                             i > start ? " " : "",
++                             i - start, text + start);
++                      bol = 1;
++                      comment_started = true;
++              }
++      }
++      if (comment_started && standalone_comment)
++              printf(" */\n\n");
++}
++
++static void
++emit_opcodes(struct wl_list *message_list, struct interface *interface)
++{
++      struct message *m;
++      int opcode;
++
++      if (wl_list_empty(message_list))
++              return;
++
++      opcode = 0;
++      wl_list_for_each(m, message_list, link)
++              printf("#define %s_%s %d\n",
++                     interface->uppercase_name, m->uppercase_name, opcode++);
++
++      printf("\n");
++}
++
++static void
++emit_opcode_versions(struct wl_list *message_list, struct interface *interface)
++{
++      struct message *m;
++
++      wl_list_for_each(m, message_list, link) {
++              printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
++              printf("#define %s_%s_SINCE_VERSION %d\n",
++                     interface->uppercase_name, m->uppercase_name, m->since);
++      }
++
++      printf("\n");
++}
++
++static void
++emit_type(struct arg *a)
++{
++      switch (a->type) {
++      default:
++      case INT:
++      case FD:
++              printf("int32_t ");
++              break;
++      case NEW_ID:
++      case UNSIGNED:
++              printf("uint32_t ");
++              break;
++      case FIXED:
++              printf("wl_fixed_t ");
++              break;
++      case STRING:
++              printf("const char *");
++              break;
++      case OBJECT:
++              printf("struct %s *", a->interface_name);
++              break;
++      case ARRAY:
++              printf("struct wl_array *");
++              break;
++      }
++}
++
++static void
++emit_stubs(struct wl_list *message_list, struct interface *interface)
++{
++      struct message *m;
++      struct arg *a, *ret;
++      int has_destructor, has_destroy;
++
++      printf("/** @ingroup iface_%s */\n", interface->name);
++      printf("static inline void\n"
++             "%s_set_user_data(struct %s *%s, void *user_data)\n"
++             "{\n"
++             "\twl_proxy_set_user_data((struct wl_proxy *) %s, user_data);\n"
++             "}\n\n",
++             interface->name, interface->name, interface->name,
++             interface->name);
++
++      printf("/** @ingroup iface_%s */\n", interface->name);
++      printf("static inline void *\n"
++             "%s_get_user_data(struct %s *%s)\n"
++             "{\n"
++             "\treturn wl_proxy_get_user_data((struct wl_proxy *) %s);\n"
++             "}\n\n",
++             interface->name, interface->name, interface->name,
++             interface->name);
++
++      printf("static inline uint32_t\n"
++             "%s_get_version(struct %s *%s)\n"
++             "{\n"
++             "\treturn wl_proxy_get_version((struct wl_proxy *) %s);\n"
++             "}\n\n",
++             interface->name, interface->name, interface->name,
++             interface->name);
++
++      has_destructor = 0;
++      has_destroy = 0;
++      wl_list_for_each(m, message_list, link) {
++              if (m->destructor)
++                      has_destructor = 1;
++              if (strcmp(m->name, "destroy") == 0)
++                      has_destroy = 1;
++      }
++
++      if (!has_destructor && has_destroy) {
++              fail(&interface->loc,
++                   "interface '%s' has method named destroy "
++                   "but no destructor",
++                   interface->name);
++              exit(EXIT_FAILURE);
++      }
++
++      if (!has_destroy && strcmp(interface->name, "wl_display") != 0) {
++              printf("/** @ingroup iface_%s */\n", interface->name);
++              printf("static inline void\n"
++                     "%s_destroy(struct %s *%s)\n"
++                     "{\n"
++                     "\twl_proxy_destroy("
++                     "(struct wl_proxy *) %s);\n"
++                     "}\n\n",
++                     interface->name, interface->name, interface->name,
++                     interface->name);
++      }
++
++      if (wl_list_empty(message_list))
++              return;
++
++      wl_list_for_each(m, message_list, link) {
++              if (m->new_id_count > 1) {
++                      warn(&m->loc,
++                           "request '%s::%s' has more than "
++                           "one new_id arg, not emitting stub\n",
++                           interface->name, m->name);
++                      continue;
++              }
++
++              ret = NULL;
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (a->type == NEW_ID)
++                              ret = a;
++              }
++
++              printf("/**\n"
++                     " * @ingroup iface_%s\n", interface->name);
++              if (m->description && m->description->text)
++                      format_text_to_comment(m->description->text, false);
++              printf(" */\n");
++              if (ret && ret->interface_name == NULL)
++                      printf("static inline void *\n");
++              else if (ret)
++                      printf("static inline struct %s *\n",
++                             ret->interface_name);
++              else
++                      printf("static inline void\n");
++
++              printf("%s_%s(struct %s *%s",
++                     interface->name, m->name,
++                     interface->name, interface->name);
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (a->type == NEW_ID && a->interface_name == NULL) {
++                              printf(", const struct wl_interface *interface"
++                                     ", uint32_t version");
++                              continue;
++                      } else if (a->type == NEW_ID)
++                              continue;
++                      printf(", ");
++                      emit_type(a);
++                      printf("%s", a->name);
++              }
++
++              printf(")\n"
++                     "{\n");
++              printf("\t");
++              if (ret) {
++                      printf("struct wl_proxy *%s;\n\n"
++                             "\t%s = ", ret->name, ret->name);
++              }
++              printf("wl_proxy_marshal_flags("
++                     "(struct wl_proxy *) %s,\n"
++                     "\t\t\t %s_%s",
++                     interface->name,
++                     interface->uppercase_name,
++                     m->uppercase_name);
++
++              if (ret) {
++                      if (ret->interface_name) {
++                              /* Normal factory case, an arg has type="new_id" and
++                               * an interface is provided */
++                              printf(", &%s_interface", ret->interface_name);
++                      } else {
++                              /* an arg has type ="new_id" but interface is not
++                               * provided, such as in wl_registry.bind */
++                              printf(", interface");
++                      }
++              } else {
++                      /* No args have type="new_id" */
++                      printf(", NULL");
++              }
++
++              if (ret && ret->interface_name == NULL)
++                      printf(", version");
++              else
++                      printf(", wl_proxy_get_version((struct wl_proxy *) %s)",
++                             interface->name);
++              printf(", %s", m->destructor ? "WL_MARSHAL_FLAG_DESTROY" : "0");
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (a->type == NEW_ID) {
++                              if (a->interface_name == NULL)
++                                      printf(", interface->name, version");
++                              printf(", NULL");
++                      } else {
++                              printf(", %s", a->name);
++                      }
++              }
++              printf(");\n");
++
++              if (ret && ret->interface_name == NULL)
++                      printf("\n\treturn (void *) %s;\n", ret->name);
++              else if (ret)
++                      printf("\n\treturn (struct %s *) %s;\n",
++                             ret->interface_name, ret->name);
++
++              printf("}\n\n");
++      }
++}
++
++static void
++emit_event_wrappers(struct wl_list *message_list, struct interface *interface)
++{
++      struct message *m;
++      struct arg *a;
++
++      /* We provide hand written functions for the display object */
++      if (strcmp(interface->name, "wl_display") == 0)
++              return;
++
++      wl_list_for_each(m, message_list, link) {
++              printf("/**\n"
++                     " * @ingroup iface_%s\n"
++                     " * Sends an %s event to the client owning the resource.\n",
++                     interface->name,
++                     m->name);
++              printf(" * @param resource_ The client's resource\n");
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (a->summary)
++                              printf(" * @param %s %s\n", a->name, a->summary);
++              }
++              printf(" */\n");
++              printf("static inline void\n"
++                     "%s_send_%s(struct wl_resource *resource_",
++                     interface->name, m->name);
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      printf(", ");
++                      switch (a->type) {
++                      case NEW_ID:
++                      case OBJECT:
++                              printf("struct wl_resource *");
++                              break;
++                      default:
++                              emit_type(a);
++                      }
++                      printf("%s", a->name);
++              }
++
++              printf(")\n"
++                     "{\n"
++                     "\twl_resource_post_event(resource_, %s_%s",
++                     interface->uppercase_name, m->uppercase_name);
++
++              wl_list_for_each(a, &m->arg_list, link)
++                      printf(", %s", a->name);
++
++              printf(");\n");
++              printf("}\n\n");
++      }
++}
++
++static void
++emit_enumerations(struct interface *interface)
++{
++      struct enumeration *e;
++      struct entry *entry;
++
++      wl_list_for_each(e, &interface->enumeration_list, link) {
++              struct description *desc = e->description;
++
++              printf("#ifndef %s_%s_ENUM\n",
++                     interface->uppercase_name, e->uppercase_name);
++              printf("#define %s_%s_ENUM\n",
++                     interface->uppercase_name, e->uppercase_name);
++
++              if (desc) {
++                      printf("/**\n");
++                      printf(" * @ingroup iface_%s\n", interface->name);
++                      format_text_to_comment(desc->summary, false);
++                      if (desc->text)
++                              format_text_to_comment(desc->text, false);
++                      printf(" */\n");
++              }
++              printf("enum %s_%s {\n", interface->name, e->name);
++              wl_list_for_each(entry, &e->entry_list, link) {
++                      desc = entry->description;
++                      if (entry->summary || entry->since > 1 || desc) {
++                              printf("\t/**\n");
++                              if (entry->summary)
++                                      printf("\t * %s\n", entry->summary);
++                              if (desc) {
++                                      printf("\t * %s\n", desc->summary);
++                                      printf("\t *\n");
++                                      if (desc->text)
++                                              desc_dump(desc->text, "\t * ");
++                              }
++                              if (entry->since > 1)
++                                      printf("\t * @since %d\n", entry->since);
++                              printf("\t */\n");
++                      }
++                      printf("\t%s_%s_%s = %s,\n",
++                             interface->uppercase_name,
++                             e->uppercase_name,
++                             entry->uppercase_name, entry->value);
++              }
++              printf("};\n");
++
++              wl_list_for_each(entry, &e->entry_list, link) {
++                      if (entry->since == 1)
++                            continue;
++
++                        printf("/**\n * @ingroup iface_%s\n */\n", interface->name);
++                        printf("#define %s_%s_%s_SINCE_VERSION %d\n",
++                               interface->uppercase_name,
++                               e->uppercase_name, entry->uppercase_name,
++                               entry->since);
++
++              }
++
++              printf("#endif /* %s_%s_ENUM */\n\n",
++                     interface->uppercase_name, e->uppercase_name);
++      }
++}
++
++static void
++emit_structs(struct wl_list *message_list, struct interface *interface, enum side side)
++{
++      struct message *m;
++      struct arg *a;
++      int n;
++
++      if (wl_list_empty(message_list))
++              return;
++
++      printf("/**\n");
++      printf(" * @ingroup iface_%s\n", interface->name);
++      printf(" * @struct %s_%s\n", interface->name,
++             (side == SERVER) ? "interface" : "listener");
++      printf(" */\n");
++      printf("struct %s_%s {\n", interface->name,
++             (side == SERVER) ? "interface" : "listener");
++
++      wl_list_for_each(m, message_list, link) {
++              struct description *mdesc = m->description;
++
++              printf("\t/**\n");
++              if (mdesc) {
++                      if (mdesc->summary)
++                              printf("\t * %s\n", mdesc->summary);
++                      printf("\t *\n");
++                      desc_dump(mdesc->text, "\t * ");
++              }
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (side == SERVER && a->type == NEW_ID &&
++                          a->interface_name == NULL)
++                              printf("\t * @param interface name of the objects interface\n"
++                                     "\t * @param version version of the objects interface\n");
++
++                      if (a->summary)
++                              printf("\t * @param %s %s\n", a->name,
++                                     a->summary);
++              }
++              if (m->since > 1) {
++                      printf("\t * @since %d\n", m->since);
++              }
++              printf("\t */\n");
++              printf("\tvoid (*%s)(", m->name);
++
++              n = strlen(m->name) + 17;
++              if (side == SERVER) {
++                      printf("struct wl_client *client,\n"
++                             "%sstruct wl_resource *resource",
++                             indent(n));
++              } else {
++                      printf("void *data,\n"),
++                      printf("%sstruct %s *%s",
++                             indent(n), interface->name, interface->name);
++              }
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      printf(",\n%s", indent(n));
++
++                      if (side == SERVER && a->type == OBJECT)
++                              printf("struct wl_resource *");
++                      else if (side == SERVER && a->type == NEW_ID && a->interface_name == NULL)
++                              printf("const char *interface, uint32_t version, uint32_t ");
++                      else if (side == CLIENT && a->type == OBJECT && a->interface_name == NULL)
++                              printf("void *");
++
++                      else if (side == CLIENT && a->type == NEW_ID)
++                              printf("struct %s *", a->interface_name);
++                      else
++                              emit_type(a);
++
++                      printf("%s", a->name);
++              }
++
++              printf(");\n");
++      }
++
++      printf("};\n\n");
++
++      if (side == CLIENT) {
++          printf("/**\n"
++                 " * @ingroup iface_%s\n"
++                 " */\n", interface->name);
++          printf("static inline int\n"
++                 "%s_add_listener(struct %s *%s,\n"
++                 "%sconst struct %s_listener *listener, void *data)\n"
++                 "{\n"
++                 "\treturn wl_proxy_add_listener((struct wl_proxy *) %s,\n"
++                 "%s(void (**)(void)) listener, data);\n"
++                 "}\n\n",
++                 interface->name, interface->name, interface->name,
++                 indent(14 + strlen(interface->name)),
++                 interface->name,
++                 interface->name,
++                 indent(37));
++      }
++}
++
++static void
++emit_types_forward_declarations(struct protocol *protocol,
++                              struct wl_list *message_list,
++                              struct wl_array *types)
++{
++      struct message *m;
++      struct arg *a;
++      int length;
++      char **p;
++
++      wl_list_for_each(m, message_list, link) {
++              length = 0;
++              m->all_null = 1;
++              wl_list_for_each(a, &m->arg_list, link) {
++                      length++;
++                      switch (a->type) {
++                      case NEW_ID:
++                      case OBJECT:
++                              if (!a->interface_name)
++                                      continue;
++
++                              m->all_null = 0;
++                              p = fail_on_null(wl_array_add(types, sizeof *p));
++                              *p = a->interface_name;
++                              break;
++                      default:
++                              break;
++                      }
++              }
++
++              if (m->all_null && length > protocol->null_run_length)
++                      protocol->null_run_length = length;
++      }
++}
++
++static int
++cmp_names(const void *p1, const void *p2)
++{
++      const char * const *s1 = p1, * const *s2 = p2;
++
++      return strcmp(*s1, *s2);
++}
++
++static const char *
++get_include_name(bool core, enum side side)
++{
++      if (side == SERVER)
++              return core ? "wayland-server-core.h" : "wayland-server.h";
++      else
++              return core ? "wayland-client-core.h" : "wayland-client.h";
++}
++
++static void
++emit_mainpage_blurb(const struct protocol *protocol, enum side side)
++{
++      struct interface *i;
++
++      printf("/**\n"
++             " * @page page_%s The %s protocol\n",
++             protocol->name, protocol->name);
++
++      if (protocol->description) {
++              if (protocol->description->summary) {
++                      printf(" * %s\n"
++                             " *\n", protocol->description->summary);
++              }
++
++              if (protocol->description->text) {
++                      printf(" * @section page_desc_%s Description\n", protocol->name);
++                      format_text_to_comment(protocol->description->text, false);
++                      printf(" *\n");
++              }
++      }
++
++      printf(" * @section page_ifaces_%s Interfaces\n", protocol->name);
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              printf(" * - @subpage page_iface_%s - %s\n",
++                     i->name,
++                     i->description && i->description->summary ?  i->description->summary : "");
++      }
++
++      if (protocol->copyright) {
++              printf(" * @section page_copyright_%s Copyright\n",
++                     protocol->name);
++              printf(" * <pre>\n");
++              format_text_to_comment(protocol->copyright, false);
++              printf(" * </pre>\n");
++      }
++
++      printf(" */\n");
++}
++
++static void
++emit_header(struct protocol *protocol, enum side side)
++{
++      struct interface *i, *i_next;
++      struct wl_array types;
++      const char *s = (side == SERVER) ? "SERVER" : "CLIENT";
++      char **p, *prev;
++
++      printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
++
++      printf("#ifndef %s_%s_PROTOCOL_H\n"
++             "#define %s_%s_PROTOCOL_H\n"
++             "\n"
++             "#include <stdint.h>\n"
++             "#include <stddef.h>\n"
++             "#include \"%s\"\n\n"
++             "#ifdef  __cplusplus\n"
++             "extern \"C\" {\n"
++             "#endif\n\n",
++             protocol->uppercase_name, s,
++             protocol->uppercase_name, s,
++             get_include_name(protocol->core_headers, side));
++      if (side == SERVER)
++              printf("struct wl_client;\n"
++                     "struct wl_resource;\n\n");
++
++      emit_mainpage_blurb(protocol, side);
++
++      wl_array_init(&types);
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              emit_types_forward_declarations(protocol, &i->request_list, &types);
++              emit_types_forward_declarations(protocol, &i->event_list, &types);
++      }
++
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              p = fail_on_null(wl_array_add(&types, sizeof *p));
++              *p = i->name;
++      }
++
++      qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
++      prev = NULL;
++      wl_array_for_each(p, &types) {
++              if (prev && strcmp(*p, prev) == 0)
++                      continue;
++              printf("struct %s;\n", *p);
++              prev = *p;
++      }
++      wl_array_release(&types);
++      printf("\n");
++
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              printf("#ifndef %s_INTERFACE\n", i->uppercase_name);
++              printf("#define %s_INTERFACE\n", i->uppercase_name);
++              printf("/**\n"
++                     " * @page page_iface_%s %s\n",
++                     i->name, i->name);
++              if (i->description && i->description->text) {
++                      printf(" * @section page_iface_%s_desc Description\n",
++                             i->name);
++                      format_text_to_comment(i->description->text, false);
++              }
++              printf(" * @section page_iface_%s_api API\n"
++                     " * See @ref iface_%s.\n"
++                     " */\n",
++                     i->name, i->name);
++              printf("/**\n"
++                     " * @defgroup iface_%s The %s interface\n",
++                     i->name, i->name);
++              if (i->description && i->description->text)
++                      format_text_to_comment(i->description->text, false);
++              printf(" */\n");
++              printf("extern const struct wl_interface "
++                     "%s_interface;\n", i->name);
++              printf("#endif\n");
++      }
++
++      printf("\n");
++
++      wl_list_for_each_safe(i, i_next, &protocol->interface_list, link) {
++
++              emit_enumerations(i);
++
++              if (side == SERVER) {
++                      emit_structs(&i->request_list, i, side);
++                      emit_opcodes(&i->event_list, i);
++                      emit_opcode_versions(&i->event_list, i);
++                      emit_opcode_versions(&i->request_list, i);
++                      emit_event_wrappers(&i->event_list, i);
++              } else {
++                      emit_structs(&i->event_list, i, side);
++                      emit_opcodes(&i->request_list, i);
++                      emit_opcode_versions(&i->event_list, i);
++                      emit_opcode_versions(&i->request_list, i);
++                      emit_stubs(&i->request_list, i);
++              }
++
++              free_interface(i);
++      }
++
++      printf("#ifdef  __cplusplus\n"
++             "}\n"
++             "#endif\n"
++             "\n"
++             "#endif\n");
++}
++
++static void
++emit_null_run(struct protocol *protocol)
++{
++      int i;
++
++      for (i = 0; i < protocol->null_run_length; i++)
++              printf("\tNULL,\n");
++}
++
++static void
++emit_types(struct protocol *protocol, struct wl_list *message_list)
++{
++      struct message *m;
++      struct arg *a;
++
++      wl_list_for_each(m, message_list, link) {
++              if (m->all_null) {
++                      m->type_index = 0;
++                      continue;
++              }
++
++              m->type_index =
++                      protocol->null_run_length + protocol->type_index;
++              protocol->type_index += m->arg_count;
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      switch (a->type) {
++                      case NEW_ID:
++                      case OBJECT:
++                              if (a->interface_name)
++                                      printf("\t&%s_interface,\n",
++                                             a->interface_name);
++                              else
++                                      printf("\tNULL,\n");
++                              break;
++                      default:
++                              printf("\tNULL,\n");
++                              break;
++                      }
++              }
++      }
++}
++
++static void
++emit_messages(const char *name, struct wl_list *message_list,
++            struct interface *interface, const char *suffix)
++{
++      struct message *m;
++      struct arg *a;
++
++      if (wl_list_empty(message_list))
++              return;
++
++      printf("static const struct wl_message "
++             "%s_%s[] = {\n",
++             interface->name, suffix);
++
++      wl_list_for_each(m, message_list, link) {
++              printf("\t{ \"%s\", \"", m->name);
++
++              if (m->since > 1)
++                      printf("%d", m->since);
++
++              wl_list_for_each(a, &m->arg_list, link) {
++                      if (is_nullable_type(a) && a->nullable)
++                              printf("?");
++
++                      switch (a->type) {
++                      default:
++                      case INT:
++                              printf("i");
++                              break;
++                      case NEW_ID:
++                              if (a->interface_name == NULL)
++                                      printf("su");
++                              printf("n");
++                              break;
++                      case UNSIGNED:
++                              printf("u");
++                              break;
++                      case FIXED:
++                              printf("f");
++                              break;
++                      case STRING:
++                              printf("s");
++                              break;
++                      case OBJECT:
++                              printf("o");
++                              break;
++                      case ARRAY:
++                              printf("a");
++                              break;
++                      case FD:
++                              printf("h");
++                              break;
++                      }
++              }
++              printf("\", %s_types + %d },\n", name, m->type_index);
++      }
++
++      printf("};\n\n");
++}
++
++
++static void
++emit_code(struct protocol *protocol, enum visibility vis)
++{
++      const char *symbol_visibility;
++      struct interface *i, *next;
++      struct wl_array types;
++      char **p, *prev;
++
++      printf("/* Generated by %s %s */\n\n", PROGRAM_NAME, WAYLAND_VERSION);
++
++      if (protocol->copyright)
++              format_text_to_comment(protocol->copyright, true);
++
++      printf("#include <stdlib.h>\n"
++             "#include <stdint.h>\n"
++             "#include \"wayland-util.h\"\n\n");
++
++      /* When building a shared library symbols must be exported, otherwise
++       * we want to have the symbols hidden. */
++      if (vis == PRIVATE) {
++              symbol_visibility = "WL_PRIVATE";
++              printf("#ifndef __has_attribute\n"
++                     "# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */\n"
++                     "#endif\n\n");
++
++              printf("#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)\n"
++                     "#define WL_PRIVATE __attribute__ ((visibility(\"hidden\")))\n"
++                     "#else\n"
++                     "#define WL_PRIVATE\n"
++                     "#endif\n\n");
++      } else {
++              symbol_visibility = "WL_EXPORT";
++      }
++
++      wl_array_init(&types);
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              emit_types_forward_declarations(protocol, &i->request_list, &types);
++              emit_types_forward_declarations(protocol, &i->event_list, &types);
++      }
++      qsort(types.data, types.size / sizeof *p, sizeof *p, cmp_names);
++      prev = NULL;
++      wl_array_for_each(p, &types) {
++              if (prev && strcmp(*p, prev) == 0)
++                      continue;
++              printf("extern const struct wl_interface %s_interface;\n", *p);
++              prev = *p;
++      }
++      wl_array_release(&types);
++      printf("\n");
++
++      printf("static const struct wl_interface *%s_types[] = {\n", protocol->name);
++      emit_null_run(protocol);
++      wl_list_for_each(i, &protocol->interface_list, link) {
++              emit_types(protocol, &i->request_list);
++              emit_types(protocol, &i->event_list);
++      }
++      printf("};\n\n");
++
++      wl_list_for_each_safe(i, next, &protocol->interface_list, link) {
++
++              emit_messages(protocol->name, &i->request_list, i, "requests");
++              emit_messages(protocol->name, &i->event_list, i, "events");
++
++              printf("%s const struct wl_interface "
++                     "%s_interface = {\n"
++                     "\t\"%s\", %d,\n",
++                     symbol_visibility, i->name, i->name, i->version);
++
++              if (!wl_list_empty(&i->request_list))
++                      printf("\t%d, %s_requests,\n",
++                             wl_list_length(&i->request_list), i->name);
++              else
++                      printf("\t0, NULL,\n");
++
++              if (!wl_list_empty(&i->event_list))
++                      printf("\t%d, %s_events,\n",
++                             wl_list_length(&i->event_list), i->name);
++              else
++                      printf("\t0, NULL,\n");
++
++              printf("};\n\n");
++
++              /* we won't need it any further */
++              free_interface(i);
++      }
++}
++
++static void
++free_protocol(struct protocol *protocol)
++{
++      free(protocol->name);
++      free(protocol->uppercase_name);
++      free(protocol->copyright);
++      free_description(protocol->description);
++}
++
++int main(int argc, char *argv[])
++{
++      struct parse_context ctx;
++      struct protocol protocol;
++      FILE *input = stdin;
++      char *input_filename = NULL;
++      int len;
++      void *buf;
++      bool help = false;
++      bool core_headers = false;
++      bool version = false;
++      bool strict = false;
++      bool fail = false;
++      int opt;
++      enum {
++              CLIENT_HEADER,
++              SERVER_HEADER,
++              PRIVATE_CODE,
++              PUBLIC_CODE,
++              CODE,
++      } mode;
++
++      static const struct option options[] = {
++              { "help",              no_argument, NULL, 'h' },
++              { "version",           no_argument, NULL, 'v' },
++              { "include-core-only", no_argument, NULL, 'c' },
++              { "strict",            no_argument, NULL, 's' },
++              { 0,                   0,           NULL, 0 }
++      };
++
++      while (1) {
++              opt = getopt_long(argc, argv, "hvcs", options, NULL);
++
++              if (opt == -1)
++                      break;
++
++              switch (opt) {
++              case 'h':
++                      help = true;
++                      break;
++              case 'v':
++                      version = true;
++                      break;
++              case 'c':
++                      core_headers = true;
++                      break;
++              case 's':
++                      strict = true;
++                      break;
++              default:
++                      fail = true;
++                      break;
++              }
++      }
++
++      argv += optind;
++      argc -= optind;
++
++      if (help)
++              usage(EXIT_SUCCESS);
++      else if (version)
++              scanner_version(EXIT_SUCCESS);
++      else if ((argc != 1 && argc != 3) || fail)
++              usage(EXIT_FAILURE);
++      else if (strcmp(argv[0], "help") == 0)
++              usage(EXIT_SUCCESS);
++      else if (strcmp(argv[0], "client-header") == 0)
++              mode = CLIENT_HEADER;
++      else if (strcmp(argv[0], "server-header") == 0)
++              mode = SERVER_HEADER;
++      else if (strcmp(argv[0], "private-code") == 0)
++              mode = PRIVATE_CODE;
++      else if (strcmp(argv[0], "public-code") == 0)
++              mode = PUBLIC_CODE;
++      else if (strcmp(argv[0], "code") == 0)
++              mode = CODE;
++      else
++              usage(EXIT_FAILURE);
++
++      if (argc == 3) {
++              input_filename = argv[1];
++              input = fopen(input_filename, "r");
++              if (input == NULL) {
++                      fprintf(stderr, "Could not open input file: %s\n",
++                              strerror(errno));
++                      exit(EXIT_FAILURE);
++              }
++              if (freopen(argv[2], "w", stdout) == NULL) {
++                      fprintf(stderr, "Could not open output file: %s\n",
++                              strerror(errno));
++                      fclose(input);
++                      exit(EXIT_FAILURE);
++              }
++      }
++
++      /* initialize protocol structure */
++      memset(&protocol, 0, sizeof protocol);
++      wl_list_init(&protocol.interface_list);
++      protocol.core_headers = core_headers;
++
++      /* initialize context */
++      memset(&ctx, 0, sizeof ctx);
++      ctx.protocol = &protocol;
++      if (input == stdin)
++              ctx.loc.filename = "<stdin>";
++      else
++              ctx.loc.filename = input_filename;
++
++      if (!is_dtd_valid(input, ctx.loc.filename)) {
++              fprintf(stderr,
++              "*******************************************************\n"
++              "*                                                     *\n"
++              "* WARNING: XML failed validation against built-in DTD *\n"
++              "*                                                     *\n"
++              "*******************************************************\n");
++              if (strict) {
++                      fclose(input);
++                      exit(EXIT_FAILURE);
++              }
++      }
++
++      /* create XML parser */
++      ctx.parser = XML_ParserCreate(NULL);
++      XML_SetUserData(ctx.parser, &ctx);
++      if (ctx.parser == NULL) {
++              fprintf(stderr, "failed to create parser\n");
++              fclose(input);
++              exit(EXIT_FAILURE);
++      }
++
++      XML_SetElementHandler(ctx.parser, start_element, end_element);
++      XML_SetCharacterDataHandler(ctx.parser, character_data);
++
++      do {
++              buf = XML_GetBuffer(ctx.parser, XML_BUFFER_SIZE);
++              len = fread(buf, 1, XML_BUFFER_SIZE, input);
++              if (len < 0) {
++                      fprintf(stderr, "fread: %s\n", strerror(errno));
++                      fclose(input);
++                      exit(EXIT_FAILURE);
++              }
++              if (XML_ParseBuffer(ctx.parser, len, len == 0) == 0) {
++                      fprintf(stderr,
++                              "Error parsing XML at line %ld col %ld: %s\n",
++                              XML_GetCurrentLineNumber(ctx.parser),
++                              XML_GetCurrentColumnNumber(ctx.parser),
++                              XML_ErrorString(XML_GetErrorCode(ctx.parser)));
++                      fclose(input);
++                      exit(EXIT_FAILURE);
++              }
++      } while (len > 0);
++
++      XML_ParserFree(ctx.parser);
++
++      switch (mode) {
++              case CLIENT_HEADER:
++                      emit_header(&protocol, CLIENT);
++                      break;
++              case SERVER_HEADER:
++                      emit_header(&protocol, SERVER);
++                      break;
++              case PRIVATE_CODE:
++                      emit_code(&protocol, PRIVATE);
++                      break;
++              case CODE:
++                      fprintf(stderr,
++                              "Using \"code\" is deprecated - use "
++                              "private-code or public-code.\n"
++                              "See the help page for details.\n");
++                      /* fallthrough */
++              case PUBLIC_CODE:
++                      emit_code(&protocol, PUBLIC);
++                      break;
++      }
++
++      free_protocol(&protocol);
++      fclose(input);
++
++      return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ce91a6f60a521ee27f72db864a17ac9b5285e492
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,292 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_CLIENT_CORE_H
++#define WAYLAND_CLIENT_CORE_H
++
++#include <stdint.h>
++#include "wayland-util.h"
++#include "wayland-version.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/** \class wl_proxy
++ *
++ * \brief Represents a protocol object on the client side.
++ *
++ * A wl_proxy acts as a client side proxy to an object existing in the
++ * compositor. The proxy is responsible for converting requests made by the
++ * clients with \ref wl_proxy_marshal() into Wayland's wire format. Events
++ * coming from the compositor are also handled by the proxy, which will in
++ * turn call the handler set with \ref wl_proxy_add_listener().
++ *
++ * \note With the exception of function \ref wl_proxy_set_queue(), functions
++ * accessing a wl_proxy are not normally used by client code. Clients
++ * should normally use the higher level interface generated by the scanner to
++ * interact with compositor objects.
++ *
++ */
++struct wl_proxy;
++
++/** \class wl_display
++ *
++ * \brief Represents a connection to the compositor and acts as a proxy to
++ * the wl_display singleton object.
++ *
++ * A wl_display object represents a client connection to a Wayland
++ * compositor. It is created with either \ref wl_display_connect() or
++ * \ref wl_display_connect_to_fd(). A connection is terminated using
++ * \ref wl_display_disconnect().
++ *
++ * A wl_display is also used as the \ref wl_proxy for the wl_display
++ * singleton object on the compositor side.
++ *
++ * A wl_display object handles all the data sent from and to the
++ * compositor. When a \ref wl_proxy marshals a request, it will write its wire
++ * representation to the display's write buffer. The data is sent to the
++ * compositor when the client calls \ref wl_display_flush().
++ *
++ * Incoming data is handled in two steps: queueing and dispatching. In the
++ * queue step, the data coming from the display fd is interpreted and
++ * added to a queue. On the dispatch step, the handler for the incoming
++ * event set by the client on the corresponding \ref wl_proxy is called.
++ *
++ * A wl_display has at least one event queue, called the <em>default
++ * queue</em>. Clients can create additional event queues with \ref
++ * wl_display_create_queue() and assign \ref wl_proxy's to it. Events
++ * occurring in a particular proxy are always queued in its assigned queue.
++ * A client can ensure that a certain assumption, such as holding a lock
++ * or running from a given thread, is true when a proxy event handler is
++ * called by assigning that proxy to an event queue and making sure that
++ * this queue is only dispatched when the assumption holds.
++ *
++ * The default queue is dispatched by calling \ref wl_display_dispatch().
++ * This will dispatch any events queued on the default queue and attempt
++ * to read from the display fd if it's empty. Events read are then queued
++ * on the appropriate queues according to the proxy assignment.
++ *
++ * A user created queue is dispatched with \ref wl_display_dispatch_queue().
++ * This function behaves exactly the same as wl_display_dispatch()
++ * but it dispatches given queue instead of the default queue.
++ *
++ * A real world example of event queue usage is Mesa's implementation of
++ * eglSwapBuffers() for the Wayland platform. This function might need
++ * to block until a frame callback is received, but dispatching the default
++ * queue could cause an event handler on the client to start drawing
++ * again. This problem is solved using another event queue, so that only
++ * the events handled by the EGL code are dispatched during the block.
++ *
++ * This creates a problem where a thread dispatches a non-default
++ * queue, reading all the data from the display fd. If the application
++ * would call \em poll(2) after that it would block, even though there
++ * might be events queued on the default queue. Those events should be
++ * dispatched with \ref wl_display_dispatch_pending() or \ref
++ * wl_display_dispatch_queue_pending() before flushing and blocking.
++ */
++struct wl_display;
++
++/** \class wl_event_queue
++ *
++ * \brief A queue for \ref wl_proxy object events.
++ *
++ * Event queues allows the events on a display to be handled in a thread-safe
++ * manner. See \ref wl_display for details.
++ *
++ */
++struct wl_event_queue;
++
++/** Destroy proxy after marshalling
++ * @ingroup wl_proxy
++ */
++#define WL_MARSHAL_FLAG_DESTROY (1 << 0)
++
++void
++wl_event_queue_destroy(struct wl_event_queue *queue);
++
++struct wl_proxy *
++wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode,
++                     const struct wl_interface *interface,
++                     uint32_t version,
++                     uint32_t flags, ...);
++
++struct wl_proxy *
++wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
++                           const struct wl_interface *interface,
++                           uint32_t version,
++                           uint32_t flags,
++                           union wl_argument *args);
++
++void
++wl_proxy_marshal(struct wl_proxy *p, uint32_t opcode, ...);
++
++void
++wl_proxy_marshal_array(struct wl_proxy *p, uint32_t opcode,
++                     union wl_argument *args);
++
++struct wl_proxy *
++wl_proxy_create(struct wl_proxy *factory,
++              const struct wl_interface *interface);
++
++void *
++wl_proxy_create_wrapper(void *proxy);
++
++void
++wl_proxy_wrapper_destroy(void *proxy_wrapper);
++
++struct wl_proxy *
++wl_proxy_marshal_constructor(struct wl_proxy *proxy,
++                           uint32_t opcode,
++                           const struct wl_interface *interface,
++                           ...);
++
++struct wl_proxy *
++wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy,
++                                     uint32_t opcode,
++                                     const struct wl_interface *interface,
++                                     uint32_t version,
++                                     ...);
++
++struct wl_proxy *
++wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
++                                 uint32_t opcode, union wl_argument *args,
++                                 const struct wl_interface *interface);
++
++struct wl_proxy *
++wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
++                                           uint32_t opcode,
++                                           union wl_argument *args,
++                                           const struct wl_interface *interface,
++                                           uint32_t version);
++
++void
++wl_proxy_destroy(struct wl_proxy *proxy);
++
++int
++wl_proxy_add_listener(struct wl_proxy *proxy,
++                    void (**implementation)(void), void *data);
++
++const void *
++wl_proxy_get_listener(struct wl_proxy *proxy);
++
++int
++wl_proxy_add_dispatcher(struct wl_proxy *proxy,
++                      wl_dispatcher_func_t dispatcher_func,
++                      const void * dispatcher_data, void *data);
++
++void
++wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data);
++
++void *
++wl_proxy_get_user_data(struct wl_proxy *proxy);
++
++uint32_t
++wl_proxy_get_version(struct wl_proxy *proxy);
++
++uint32_t
++wl_proxy_get_id(struct wl_proxy *proxy);
++
++void
++wl_proxy_set_tag(struct wl_proxy *proxy,
++               const char * const *tag);
++
++const char * const *
++wl_proxy_get_tag(struct wl_proxy *proxy);
++
++const char *
++wl_proxy_get_class(struct wl_proxy *proxy);
++
++void
++wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
++
++struct wl_display *
++wl_display_connect(const char *name);
++
++struct wl_display *
++wl_display_connect_to_fd(int fd);
++
++void
++wl_display_disconnect(struct wl_display *display);
++
++int
++wl_display_get_fd(struct wl_display *display);
++
++int
++wl_display_dispatch(struct wl_display *display);
++
++int
++wl_display_dispatch_queue(struct wl_display *display,
++                        struct wl_event_queue *queue);
++
++int
++wl_display_dispatch_queue_pending(struct wl_display *display,
++                                struct wl_event_queue *queue);
++
++int
++wl_display_dispatch_pending(struct wl_display *display);
++
++int
++wl_display_get_error(struct wl_display *display);
++
++uint32_t
++wl_display_get_protocol_error(struct wl_display *display,
++                            const struct wl_interface **interface,
++                            uint32_t *id);
++
++int
++wl_display_flush(struct wl_display *display);
++
++int
++wl_display_roundtrip_queue(struct wl_display *display,
++                         struct wl_event_queue *queue);
++
++int
++wl_display_roundtrip(struct wl_display *display);
++
++struct wl_event_queue *
++wl_display_create_queue(struct wl_display *display);
++
++int
++wl_display_prepare_read_queue(struct wl_display *display,
++                            struct wl_event_queue *queue);
++
++int
++wl_display_prepare_read(struct wl_display *display);
++
++void
++wl_display_cancel_read(struct wl_display *display);
++
++int
++wl_display_read_events(struct wl_display *display);
++
++void
++wl_log_set_handler_client(wl_log_func_t handler);
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..90fb9c7def555679319acdf3fb139ffefd4cc34b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2444 @@@
++/*
++ * Copyright © 2008-2012 Kristian Høgsberg
++ * Copyright © 2010-2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdbool.h>
++#include <errno.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <ctype.h>
++#include <assert.h>
++#include <fcntl.h>
++#include <poll.h>
++#include <pthread.h>
++
++#include "wayland-util.h"
++#include "wayland-os.h"
++#include "wayland-client.h"
++#include "wayland-private.h"
++
++/** \cond */
++
++enum wl_proxy_flag {
++      WL_PROXY_FLAG_ID_DELETED = (1 << 0),
++      WL_PROXY_FLAG_DESTROYED = (1 << 1),
++      WL_PROXY_FLAG_WRAPPER = (1 << 2),
++};
++
++struct wl_zombie {
++      int event_count;
++      int *fd_count;
++};
++
++struct wl_proxy {
++      struct wl_object object;
++      struct wl_display *display;
++      struct wl_event_queue *queue;
++      uint32_t flags;
++      int refcount;
++      void *user_data;
++      wl_dispatcher_func_t dispatcher;
++      uint32_t version;
++      const char * const *tag;
++};
++
++struct wl_event_queue {
++      struct wl_list event_list;
++      struct wl_display *display;
++};
++
++struct wl_display {
++      struct wl_proxy proxy;
++      struct wl_connection *connection;
++
++      /* errno of the last wl_display error */
++      int last_error;
++
++      /* When display gets an error event from some object, it stores
++       * information about it here, so that client can get this
++       * information afterwards */
++      struct {
++              /* Code of the error. It can be compared to
++               * the interface's errors enumeration. */
++              uint32_t code;
++              /* interface (protocol) in which the error occurred */
++              const struct wl_interface *interface;
++              /* id of the proxy that caused the error. There's no warranty
++               * that the proxy is still valid. It's up to client how it will
++               * use it */
++              uint32_t id;
++      } protocol_error;
++      int fd;
++      struct wl_map objects;
++      struct wl_event_queue display_queue;
++      struct wl_event_queue default_queue;
++      pthread_mutex_t mutex;
++
++      int reader_count;
++      uint32_t read_serial;
++      pthread_cond_t reader_cond;
++};
++
++/** \endcond */
++
++static int debug_client = 0;
++
++/**
++ * This helper function wakes up all threads that are
++ * waiting for display->reader_cond (i. e. when reading is done,
++ * canceled, or an error occurred)
++ *
++ * NOTE: must be called with display->mutex locked
++ */
++static void
++display_wakeup_threads(struct wl_display *display)
++{
++      /* Thread can get sleeping only in read_events(). If we're
++       * waking it up, it means that the read completed or was
++       * canceled, so we must increase the read_serial.
++       * This prevents from indefinite sleeping in read_events().
++       */
++      ++display->read_serial;
++
++      pthread_cond_broadcast(&display->reader_cond);
++}
++
++/**
++ * This function is called for local errors (no memory, server hung up)
++ *
++ * \param display
++ * \param error    error value (EINVAL, EFAULT, ...)
++ *
++ * \note this function is called with display mutex locked
++ */
++static void
++display_fatal_error(struct wl_display *display, int error)
++{
++      if (display->last_error)
++              return;
++
++      if (!error)
++              error = EFAULT;
++
++      display->last_error = error;
++
++      display_wakeup_threads(display);
++}
++
++/**
++ * This function is called for error events
++ * and indicates that in some object an error occurred.
++ * The difference between this function and display_fatal_error()
++ * is that this one handles errors that will come by wire,
++ * whereas display_fatal_error() is called for local errors.
++ *
++ * \param display
++ * \param code    error code
++ * \param id      id of the object that generated the error
++ * \param intf    protocol interface
++ */
++static void
++display_protocol_error(struct wl_display *display, uint32_t code,
++                     uint32_t id, const struct wl_interface *intf)
++{
++      int err;
++
++      if (display->last_error)
++              return;
++
++      /* set correct errno */
++      if (intf && wl_interface_equal(intf, &wl_display_interface)) {
++              switch (code) {
++              case WL_DISPLAY_ERROR_INVALID_OBJECT:
++              case WL_DISPLAY_ERROR_INVALID_METHOD:
++                      err = EINVAL;
++                      break;
++              case WL_DISPLAY_ERROR_NO_MEMORY:
++                      err = ENOMEM;
++                      break;
++              case WL_DISPLAY_ERROR_IMPLEMENTATION:
++                      err = EPROTO;
++                      break;
++              default:
++                      err = EFAULT;
++              }
++      } else {
++              err = EPROTO;
++      }
++
++      pthread_mutex_lock(&display->mutex);
++
++      display->last_error = err;
++
++      display->protocol_error.code = code;
++      display->protocol_error.id = id;
++      display->protocol_error.interface = intf;
++
++      /*
++       * here it is not necessary to wake up threads like in
++       * display_fatal_error, because this function is called from
++       * an event handler and that means that read_events() is done
++       * and woke up all threads. Since wl_display_prepare_read()
++       * fails when there are events in the queue, no threads
++       * can sleep in read_events() during dispatching
++       * (and therefore during calling this function), so this is safe.
++       */
++
++      pthread_mutex_unlock(&display->mutex);
++}
++
++static void
++wl_event_queue_init(struct wl_event_queue *queue, struct wl_display *display)
++{
++      wl_list_init(&queue->event_list);
++      queue->display = display;
++}
++
++static void
++wl_proxy_unref(struct wl_proxy *proxy)
++{
++      assert(proxy->refcount > 0);
++      if (--proxy->refcount > 0)
++              return;
++
++      /* If we get here, the client must have explicitly requested
++       * deletion. */
++      assert(proxy->flags & WL_PROXY_FLAG_DESTROYED);
++      free(proxy);
++}
++
++static void
++validate_closure_objects(struct wl_closure *closure)
++{
++      const char *signature;
++      struct argument_details arg;
++      int i, count;
++      struct wl_proxy *proxy;
++
++      signature = closure->message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'n':
++              case 'o':
++                      proxy = (struct wl_proxy *) closure->args[i].o;
++                      if (proxy && proxy->flags & WL_PROXY_FLAG_DESTROYED)
++                              closure->args[i].o = NULL;
++                      break;
++              default:
++                      break;
++              }
++      }
++}
++
++/* Destroys a closure which was demarshaled for dispatch; unrefs all the
++ * proxies in its arguments, as well as its own proxy, and destroys the
++ * closure itself. */
++static void
++destroy_queued_closure(struct wl_closure *closure)
++{
++      const char *signature;
++      struct argument_details arg;
++      struct wl_proxy *proxy;
++      int i, count;
++
++      signature = closure->message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'n':
++              case 'o':
++                      proxy = (struct wl_proxy *) closure->args[i].o;
++                      if (proxy)
++                              wl_proxy_unref(proxy);
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      wl_proxy_unref(closure->proxy);
++      wl_closure_destroy(closure);
++}
++
++static void
++wl_event_queue_release(struct wl_event_queue *queue)
++{
++      struct wl_closure *closure;
++
++      while (!wl_list_empty(&queue->event_list)) {
++              closure = wl_container_of(queue->event_list.next,
++                                        closure, link);
++              wl_list_remove(&closure->link);
++              destroy_queued_closure(closure);
++      }
++}
++
++/** Destroy an event queue
++ *
++ * \param queue The event queue to be destroyed
++ *
++ * Destroy the given event queue. Any pending event on that queue is
++ * discarded.
++ *
++ * The \ref wl_display object used to create the queue should not be
++ * destroyed until all event queues created with it are destroyed with
++ * this function.
++ *
++ * \memberof wl_event_queue
++ */
++WL_EXPORT void
++wl_event_queue_destroy(struct wl_event_queue *queue)
++{
++      struct wl_display *display = queue->display;
++
++      pthread_mutex_lock(&display->mutex);
++      wl_event_queue_release(queue);
++      free(queue);
++      pthread_mutex_unlock(&display->mutex);
++}
++
++/** Create a new event queue for this display
++ *
++ * \param display The display context object
++ * \return A new event queue associated with this display or NULL on
++ * failure.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_event_queue *
++wl_display_create_queue(struct wl_display *display)
++{
++      struct wl_event_queue *queue;
++
++      queue = zalloc(sizeof *queue);
++      if (queue == NULL)
++              return NULL;
++
++      wl_event_queue_init(queue, display);
++
++      return queue;
++}
++
++static int
++message_count_fds(const char *signature)
++{
++      unsigned int count, i, fds = 0;
++      struct argument_details arg;
++
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              if (arg.type == 'h')
++                      fds++;
++      }
++
++      return fds;
++}
++
++static struct wl_zombie *
++prepare_zombie(struct wl_proxy *proxy)
++{
++      const struct wl_interface *interface = proxy->object.interface;
++      const struct wl_message *message;
++      int i, count;
++      struct wl_zombie *zombie = NULL;
++
++      /* If we hit an event with an FD, ensure we have a zombie object and
++       * fill the fd_count slot for that event with the number of FDs for
++       * that event. Interfaces with no events containing FDs will not have
++       * zombie objects created. */
++      for (i = 0; i < interface->event_count; i++) {
++              message = &interface->events[i];
++              count = message_count_fds(message->signature);
++
++              if (!count)
++                      continue;
++
++              if (!zombie) {
++                      zombie = zalloc(sizeof(*zombie) +
++                                      (interface->event_count * sizeof(int)));
++                      if (!zombie)
++                              return NULL;
++
++                      zombie->event_count = interface->event_count;
++                      zombie->fd_count = (int *) &zombie[1];
++              }
++
++              zombie->fd_count[i] = count;
++      }
++
++      return zombie;
++}
++
++static enum wl_iterator_result
++free_zombies(void *element, void *data, uint32_t flags)
++{
++      if (flags & WL_MAP_ENTRY_ZOMBIE)
++              free(element);
++
++      return WL_ITERATOR_CONTINUE;
++}
++
++static struct wl_proxy *
++proxy_create(struct wl_proxy *factory, const struct wl_interface *interface,
++           uint32_t version)
++{
++      struct wl_proxy *proxy;
++      struct wl_display *display = factory->display;
++
++      proxy = zalloc(sizeof *proxy);
++      if (proxy == NULL)
++              return NULL;
++
++      proxy->object.interface = interface;
++      proxy->display = display;
++      proxy->queue = factory->queue;
++      proxy->refcount = 1;
++      proxy->version = version;
++
++      proxy->object.id = wl_map_insert_new(&display->objects, 0, proxy);
++      if (proxy->object.id == 0) {
++              free(proxy);
++              return NULL;
++      }
++
++      return proxy;
++}
++
++/** Create a proxy object with a given interface
++ *
++ * \param factory Factory proxy object
++ * \param interface Interface the proxy object should use
++ * \return A newly allocated proxy object or NULL on failure
++ *
++ * This function creates a new proxy object with the supplied interface. The
++ * proxy object will have an id assigned from the client id space. The id
++ * should be created on the compositor side by sending an appropriate request
++ * with \ref wl_proxy_marshal().
++ *
++ * The proxy will inherit the display and event queue of the factory object.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \sa wl_display, wl_event_queue, wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
++{
++      struct wl_display *display = factory->display;
++      struct wl_proxy *proxy;
++
++      pthread_mutex_lock(&display->mutex);
++      proxy = proxy_create(factory, interface, factory->version);
++      pthread_mutex_unlock(&display->mutex);
++
++      return proxy;
++}
++
++/* The caller should hold the display lock */
++static struct wl_proxy *
++wl_proxy_create_for_id(struct wl_proxy *factory,
++                     uint32_t id, const struct wl_interface *interface)
++{
++      struct wl_proxy *proxy;
++      struct wl_display *display = factory->display;
++
++      proxy = zalloc(sizeof *proxy);
++      if (proxy == NULL)
++              return NULL;
++
++      proxy->object.interface = interface;
++      proxy->object.id = id;
++      proxy->display = display;
++      proxy->queue = factory->queue;
++      proxy->refcount = 1;
++      proxy->version = factory->version;
++
++      if (wl_map_insert_at(&display->objects, 0, id, proxy) == -1) {
++              free(proxy);
++              return NULL;
++      }
++
++      return proxy;
++}
++
++static void
++proxy_destroy(struct wl_proxy *proxy)
++{
++      if (proxy->flags & WL_PROXY_FLAG_ID_DELETED) {
++              wl_map_remove(&proxy->display->objects, proxy->object.id);
++      } else if (proxy->object.id < WL_SERVER_ID_START) {
++              struct wl_zombie *zombie = prepare_zombie(proxy);
++
++              /* The map now contains the zombie entry, until the delete_id
++               * event arrives. */
++              wl_map_insert_at(&proxy->display->objects,
++                               WL_MAP_ENTRY_ZOMBIE,
++                               proxy->object.id,
++                               zombie);
++      } else {
++              wl_map_insert_at(&proxy->display->objects, 0,
++                               proxy->object.id, NULL);
++      }
++
++      proxy->flags |= WL_PROXY_FLAG_DESTROYED;
++
++      wl_proxy_unref(proxy);
++}
++
++static void
++wl_proxy_destroy_caller_locks(struct wl_proxy *proxy)
++{
++      if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++              wl_abort("Tried to destroy wrapper with wl_proxy_destroy()\n");
++
++      proxy_destroy(proxy);
++}
++
++/** Destroy a proxy object
++ *
++ * \param proxy The proxy to be destroyed
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \note This function will abort in response to egregious
++ * errors, and will do so with the display lock held. This means
++ * SIGABRT handlers must not perform any actions that would
++ * attempt to take that lock, or a deadlock would occur.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_destroy(struct wl_proxy *proxy)
++{
++      struct wl_display *display = proxy->display;
++
++      pthread_mutex_lock(&display->mutex);
++
++      wl_proxy_destroy_caller_locks(proxy);
++
++      pthread_mutex_unlock(&display->mutex);
++}
++
++/** Set a proxy's listener
++ *
++ * \param proxy The proxy object
++ * \param implementation The listener to be added to proxy
++ * \param data User data to be associated with the proxy
++ * \return 0 on success or -1 on failure
++ *
++ * Set proxy's listener to \c implementation and its user data to
++ * \c data. If a listener has already been set, this function
++ * fails and nothing is changed.
++ *
++ * \c implementation is a vector of function pointers. For an opcode
++ * \c n, \c implementation[n] should point to the handler of \c n for
++ * the given object.
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT int
++wl_proxy_add_listener(struct wl_proxy *proxy,
++                    void (**implementation)(void), void *data)
++{
++      if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++              wl_abort("Proxy %p is a wrapper\n", proxy);
++
++      if (proxy->object.implementation || proxy->dispatcher) {
++              wl_log("proxy %p already has listener\n", proxy);
++              return -1;
++      }
++
++      proxy->object.implementation = implementation;
++      proxy->user_data = data;
++
++      return 0;
++}
++
++/** Get a proxy's listener
++ *
++ * \param proxy The proxy object
++ * \return The address of the proxy's listener or NULL if no listener is set
++ *
++ * Gets the address to the proxy's listener; which is the listener set with
++ * \ref wl_proxy_add_listener.
++ *
++ * This function is useful in clients with multiple listeners on the same
++ * interface to allow the identification of which code to execute.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT const void *
++wl_proxy_get_listener(struct wl_proxy *proxy)
++{
++      return proxy->object.implementation;
++}
++
++/** Set a proxy's listener (with dispatcher)
++ *
++ * \param proxy The proxy object
++ * \param dispatcher The dispatcher to be used for this proxy
++ * \param implementation The dispatcher-specific listener implementation
++ * \param data User data to be associated with the proxy
++ * \return 0 on success or -1 on failure
++ *
++ * Set proxy's listener to use \c dispatcher_func as its dispatcher and \c
++ * dispatcher_data as its dispatcher-specific implementation and its user data
++ * to \c data. If a listener has already been set, this function
++ * fails and nothing is changed.
++ *
++ * The exact details of dispatcher_data depend on the dispatcher used.  This
++ * function is intended to be used by language bindings, not user code.
++ *
++ * \c proxy must not be a proxy wrapper.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT int
++wl_proxy_add_dispatcher(struct wl_proxy *proxy,
++                      wl_dispatcher_func_t dispatcher,
++                      const void *implementation, void *data)
++{
++      if (proxy->flags & WL_PROXY_FLAG_WRAPPER)
++              wl_abort("Proxy %p is a wrapper\n", proxy);
++
++      if (proxy->object.implementation || proxy->dispatcher) {
++              wl_log("proxy %p already has listener\n", proxy);
++              return -1;
++      }
++
++      proxy->object.implementation = implementation;
++      proxy->dispatcher = dispatcher;
++      proxy->user_data = data;
++
++      return 0;
++}
++
++static struct wl_proxy *
++create_outgoing_proxy(struct wl_proxy *proxy, const struct wl_message *message,
++                    union wl_argument *args,
++                    const struct wl_interface *interface, uint32_t version)
++{
++      int i, count;
++      const char *signature;
++      struct argument_details arg;
++      struct wl_proxy *new_proxy = NULL;
++
++      signature = message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++
++              switch (arg.type) {
++              case 'n':
++                      new_proxy = proxy_create(proxy, interface, version);
++                      if (new_proxy == NULL)
++                              return NULL;
++
++                      args[i].o = &new_proxy->object;
++                      break;
++              }
++      }
++
++      return new_proxy;
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ * \param interface The interface to use for the new proxy
++ *
++ * This function translates a request given an opcode, an interface and a
++ * wl_argument array to the wire format and writes it to the connection
++ * buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will inherit their version from their parent.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_constructor(struct wl_proxy *proxy,
++                                 uint32_t opcode, union wl_argument *args,
++                                 const struct wl_interface *interface)
++{
++      return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
++                                                          args, interface,
++                                                          proxy->version);
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version for the new proxy
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.  This version takes an
++ * array of the union type wl_argument.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will have the version specified.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_constructor_versioned(struct wl_proxy *proxy,
++                                           uint32_t opcode,
++                                           union wl_argument *args,
++                                           const struct wl_interface *interface,
++                                           uint32_t version)
++{
++      return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, 0, args);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version of the new proxy
++ * \param flags Flags that modify marshalling behaviour
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will have the version specified.
++ *
++ * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy
++ * is destroyed atomically with the marshalling in order to prevent
++ * races that can occur if the display lock is dropped between the
++ * marshal and destroy operations.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_flags(struct wl_proxy *proxy, uint32_t opcode,
++                     const struct wl_interface *interface, uint32_t version,
++                     uint32_t flags, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      va_list ap;
++
++      va_start(ap, flags);
++      wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      return wl_proxy_marshal_array_flags(proxy, opcode, interface, version, flags, args);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version for the new proxy
++ * \param flags Flags that modify marshalling behaviour
++ * \param args Extra arguments for the given request
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.  This version takes an
++ * array of the union type wl_argument.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will have the version specified.
++ *
++ * The flag WL_MARSHAL_FLAG_DESTROY may be passed to ensure the proxy
++ * is destroyed atomically with the marshalling in order to prevent
++ * races that can occur if the display lock is dropped between the
++ * marshal and destroy operations.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal_flags()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_array_flags(struct wl_proxy *proxy, uint32_t opcode,
++                           const struct wl_interface *interface, uint32_t version,
++                           uint32_t flags, union wl_argument *args)
++{
++      struct wl_closure *closure;
++      struct wl_proxy *new_proxy = NULL;
++      const struct wl_message *message;
++      struct wl_display *disp = proxy->display;
++
++      pthread_mutex_lock(&disp->mutex);
++
++      message = &proxy->object.interface->methods[opcode];
++      if (interface) {
++              new_proxy = create_outgoing_proxy(proxy, message,
++                                                args, interface,
++                                                version);
++              if (new_proxy == NULL)
++                      goto err_unlock;
++      }
++
++      if (proxy->display->last_error) {
++              goto err_unlock;
++      }
++
++      closure = wl_closure_marshal(&proxy->object, opcode, args, message);
++      if (closure == NULL) {
++              wl_log("Error marshalling request: %s\n", strerror(errno));
++              display_fatal_error(proxy->display, errno);
++              goto err_unlock;
++      }
++
++      if (debug_client)
++              wl_closure_print(closure, &proxy->object, true, false, NULL);
++
++      if (wl_closure_send(closure, proxy->display->connection)) {
++              wl_log("Error sending request: %s\n", strerror(errno));
++              display_fatal_error(proxy->display, errno);
++      }
++
++      wl_closure_destroy(closure);
++
++ err_unlock:
++      if (flags & WL_MARSHAL_FLAG_DESTROY)
++              wl_proxy_destroy_caller_locks(proxy);
++
++      pthread_mutex_unlock(&disp->mutex);
++
++      return new_proxy;
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param ... Extra arguments for the given request
++ *
++ * This function is similar to wl_proxy_marshal_constructor(), except
++ * it doesn't create proxies for new-id arguments.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \sa wl_proxy_create()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      va_list ap;
++
++      va_start(ap, opcode);
++      wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      wl_proxy_marshal_array_constructor(proxy, opcode, args, NULL);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * This function translates a request given an opcode, an interface and extra
++ * arguments to the wire format and writes it to the connection buffer. The
++ * types of the extra arguments must correspond to the argument types of the
++ * method associated with the opcode in the interface.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will inherit their version from their parent.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_constructor(struct wl_proxy *proxy, uint32_t opcode,
++                           const struct wl_interface *interface, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      va_list ap;
++
++      va_start(ap, interface);
++      wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      return wl_proxy_marshal_array_constructor(proxy, opcode,
++                                                args, interface);
++}
++
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param interface The interface to use for the new proxy
++ * \param version The protocol object version of the new proxy
++ * \param ... Extra arguments for the given request
++ * \return A new wl_proxy for the new_id argument or NULL on error
++ *
++ * Translates the request given by opcode and the extra arguments into the
++ * wire format and write it to the connection buffer.
++ *
++ * For new-id arguments, this function will allocate a new wl_proxy
++ * and send the ID to the server.  The new wl_proxy will be returned
++ * on success or NULL on error with errno set accordingly.  The newly
++ * created proxy will have the version specified.
++ *
++ * \note This should not normally be used by non-generated code.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT struct wl_proxy *
++wl_proxy_marshal_constructor_versioned(struct wl_proxy *proxy, uint32_t opcode,
++                                     const struct wl_interface *interface,
++                                     uint32_t version, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      va_list ap;
++
++      va_start(ap, version);
++      wl_argument_from_va_list(proxy->object.interface->methods[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      return wl_proxy_marshal_array_constructor_versioned(proxy, opcode,
++                                                          args, interface,
++                                                          version);
++}
++
++/** Prepare a request to be sent to the compositor
++ *
++ * \param proxy The proxy object
++ * \param opcode Opcode of the request to be sent
++ * \param args Extra arguments for the given request
++ *
++ * This function is similar to wl_proxy_marshal_array_constructor(), except
++ * it doesn't create proxies for new-id arguments.
++ *
++ * \note This is intended to be used by language bindings and not in
++ * non-generated code.
++ *
++ * \sa wl_proxy_marshal()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_marshal_array(struct wl_proxy *proxy, uint32_t opcode,
++                     union wl_argument *args)
++{
++      wl_proxy_marshal_array_constructor(proxy, opcode, args, NULL);
++}
++
++static void
++display_handle_error(void *data,
++                   struct wl_display *display, void *object,
++                   uint32_t code, const char *message)
++{
++      struct wl_proxy *proxy = object;
++      uint32_t object_id;
++      const struct wl_interface *interface;
++
++      if (proxy) {
++              wl_log("%s@%u: error %d: %s\n",
++                     proxy->object.interface->name,
++                     proxy->object.id,
++                     code, message);
++
++              object_id = proxy->object.id;
++              interface = proxy->object.interface;
++      } else {
++              wl_log("[destroyed object]: error %d: %s\n",
++                     code, message);
++
++              object_id = 0;
++              interface = NULL;
++      }
++
++      display_protocol_error(display, code, object_id, interface);
++}
++
++static void
++display_handle_delete_id(void *data, struct wl_display *display, uint32_t id)
++{
++      struct wl_proxy *proxy;
++
++      pthread_mutex_lock(&display->mutex);
++
++      proxy = wl_map_lookup(&display->objects, id);
++
++      if (wl_object_is_zombie(&display->objects, id)) {
++              /* For zombie objects, the 'proxy' is actually the zombie
++               * event-information structure, which we can free. */
++              free(proxy);
++              wl_map_remove(&display->objects, id);
++      } else if (proxy) {
++              proxy->flags |= WL_PROXY_FLAG_ID_DELETED;
++      } else {
++              wl_log("error: received delete_id for unknown id (%u)\n", id);
++      }
++
++      pthread_mutex_unlock(&display->mutex);
++}
++
++static const struct wl_display_listener display_listener = {
++      display_handle_error,
++      display_handle_delete_id
++};
++
++static int
++connect_to_socket(const char *name)
++{
++      struct sockaddr_un addr;
++      socklen_t size;
++      const char *runtime_dir;
++      int name_size, fd;
++      bool path_is_absolute;
++
++      if (name == NULL)
++              name = getenv("WAYLAND_DISPLAY");
++      if (name == NULL)
++              name = "wayland-0";
++
++      path_is_absolute = name[0] == '/';
++
++      runtime_dir = getenv("XDG_RUNTIME_DIR");
++      if (((!runtime_dir || runtime_dir[0] != '/') && !path_is_absolute)) {
++              wl_log("error: XDG_RUNTIME_DIR is invalid or not set in the environment.\n");
++              /* to prevent programs reporting
++               * "failed to create display: Success" */
++              errno = ENOENT;
++              return -1;
++      }
++
++      fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++      if (fd < 0)
++              return -1;
++
++      memset(&addr, 0, sizeof addr);
++      addr.sun_family = AF_LOCAL;
++      if (!path_is_absolute) {
++              name_size =
++                      snprintf(addr.sun_path, sizeof addr.sun_path,
++                               "%s/%s", runtime_dir, name) + 1;
++      } else {
++              /* absolute path */
++              name_size =
++                      snprintf(addr.sun_path, sizeof addr.sun_path,
++                               "%s", name) + 1;
++      }
++
++      assert(name_size > 0);
++      if (name_size > (int)sizeof addr.sun_path) {
++              if (!path_is_absolute) {
++                      wl_log("error: socket path \"%s/%s\" plus null terminator"
++                             " exceeds %i bytes\n", runtime_dir, name, (int) sizeof(addr.sun_path));
++              } else {
++                      wl_log("error: socket path \"%s\" plus null terminator"
++                             " exceeds %i bytes\n", name, (int) sizeof(addr.sun_path));
++              }
++              close(fd);
++              /* to prevent programs reporting
++               * "failed to add socket: Success" */
++              errno = ENAMETOOLONG;
++              return -1;
++      };
++
++      size = offsetof (struct sockaddr_un, sun_path) + name_size;
++
++      if (connect(fd, (struct sockaddr *) &addr, size) < 0) {
++              close(fd);
++              return -1;
++      }
++
++      return fd;
++}
++
++/** Connect to Wayland display on an already open fd
++ *
++ * \param fd The fd to use for the connection
++ * \return A \ref wl_display object or \c NULL on failure
++ *
++ * The wl_display takes ownership of the fd and will close it when the
++ * display is destroyed.  The fd will also be closed in case of
++ * failure.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_connect_to_fd(int fd)
++{
++      struct wl_display *display;
++      const char *debug;
++
++      debug = getenv("WAYLAND_DEBUG");
++      if (debug && (strstr(debug, "client") || strstr(debug, "1")))
++              debug_client = 1;
++
++      display = zalloc(sizeof *display);
++      if (display == NULL) {
++              close(fd);
++              return NULL;
++      }
++
++      display->fd = fd;
++      wl_map_init(&display->objects, WL_MAP_CLIENT_SIDE);
++      wl_event_queue_init(&display->default_queue, display);
++      wl_event_queue_init(&display->display_queue, display);
++      pthread_mutex_init(&display->mutex, NULL);
++      pthread_cond_init(&display->reader_cond, NULL);
++      display->reader_count = 0;
++
++      if (wl_map_insert_at(&display->objects, 0, 0, NULL) == -1)
++              goto err_connection;
++
++      display->proxy.object.id =
++              wl_map_insert_new(&display->objects, 0, display);
++
++      if (display->proxy.object.id == 0)
++              goto err_connection;
++
++      display->proxy.object.interface = &wl_display_interface;
++      display->proxy.display = display;
++      display->proxy.object.implementation = (void(**)(void)) &display_listener;
++      display->proxy.user_data = display;
++      display->proxy.queue = &display->default_queue;
++      display->proxy.flags = 0;
++      display->proxy.refcount = 1;
++
++      /* We set this version to 0 for backwards compatibility.
++       *
++       * If a client is using old versions of protocol headers,
++       * it will use unversioned API to create proxies.  Those
++       * proxies will inherit this 0.
++       *
++       * A client could be passing these proxies into library
++       * code newer than the headers that checks proxy
++       * versions.  When the proxy version is reported as 0
++       * the library will know that it can't reliably determine
++       * the proxy version, and should do whatever fallback is
++       * required.
++       *
++       * This trick forces wl_display to always report 0, but
++       * since it's a special object that we can't bind
++       * specific versions of anyway, this should be fine.
++       */
++      display->proxy.version = 0;
++
++      display->connection = wl_connection_create(display->fd);
++      if (display->connection == NULL)
++              goto err_connection;
++
++      return display;
++
++ err_connection:
++      pthread_mutex_destroy(&display->mutex);
++      pthread_cond_destroy(&display->reader_cond);
++      wl_map_release(&display->objects);
++      close(display->fd);
++      free(display);
++
++      return NULL;
++}
++
++/** Connect to a Wayland display
++ *
++ * \param name Name of the Wayland display to connect to
++ * \return A \ref wl_display object or \c NULL on failure
++ *
++ * Connect to the Wayland display named \c name. If \c name is \c NULL,
++ * its value will be replaced with the WAYLAND_DISPLAY environment
++ * variable if it is set, otherwise display "wayland-0" will be used.
++ *
++ * If WAYLAND_SOCKET is set, it's interpreted as a file descriptor number
++ * referring to an already opened socket. In this case, the socket is used
++ * as-is and \c name is ignored.
++ *
++ * If \c name is a relative path, then the socket is opened relative to
++ * the XDG_RUNTIME_DIR directory.
++ *
++ * If \c name is an absolute path, then that path is used as-is for
++ * the location of the socket at which the Wayland server is listening;
++ * no qualification inside XDG_RUNTIME_DIR is attempted.
++ *
++ * If \c name is \c NULL and the WAYLAND_DISPLAY environment variable
++ * is set to an absolute pathname, then that pathname is used as-is
++ * for the socket in the same manner as if \c name held an absolute
++ * path. Support for absolute paths in \c name and WAYLAND_DISPLAY
++ * is present since Wayland version 1.15.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_connect(const char *name)
++{
++      char *connection, *end;
++      int flags, fd;
++
++      connection = getenv("WAYLAND_SOCKET");
++      if (connection) {
++              int prev_errno = errno;
++              errno = 0;
++              fd = strtol(connection, &end, 10);
++              if (errno != 0 || connection == end || *end != '\0')
++                      return NULL;
++              errno = prev_errno;
++
++              flags = fcntl(fd, F_GETFD);
++              if (flags == -1 && errno == EBADF)
++                      return NULL;
++              else if (flags != -1)
++                      fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
++              unsetenv("WAYLAND_SOCKET");
++      } else {
++              fd = connect_to_socket(name);
++              if (fd < 0)
++                      return NULL;
++      }
++
++      return wl_display_connect_to_fd(fd);
++}
++
++/** Close a connection to a Wayland display
++ *
++ * \param display The display context object
++ *
++ * Close the connection to \c display and free all resources associated
++ * with it.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_disconnect(struct wl_display *display)
++{
++      wl_connection_destroy(display->connection);
++      wl_map_for_each(&display->objects, free_zombies, NULL);
++      wl_map_release(&display->objects);
++      wl_event_queue_release(&display->default_queue);
++      wl_event_queue_release(&display->display_queue);
++      pthread_mutex_destroy(&display->mutex);
++      pthread_cond_destroy(&display->reader_cond);
++      close(display->fd);
++
++      free(display);
++}
++
++/** Get a display context's file descriptor
++ *
++ * \param display The display context object
++ * \return Display object file descriptor
++ *
++ * Return the file descriptor associated with a display so it can be
++ * integrated into the client's main loop.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_get_fd(struct wl_display *display)
++{
++      return display->fd;
++}
++
++static void
++sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
++{
++      int *done = data;
++
++      *done = 1;
++      wl_callback_destroy(callback);
++}
++
++static const struct wl_callback_listener sync_listener = {
++      sync_callback
++};
++
++/** Block until all pending request are processed by the server
++ *
++ * \param display The display context object
++ * \param queue The queue on which to run the roundtrip
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * This function blocks until the server has processed all currently issued
++ * requests by sending a request to the display server and waiting for a
++ * reply before returning.
++ *
++ * This function uses wl_display_dispatch_queue() internally. It is not allowed
++ * to call this function while the thread is being prepared for reading events,
++ * and doing so will cause a dead lock.
++ *
++ * \note This function may dispatch other events being received on the given
++ * queue.
++ *
++ * \sa wl_display_roundtrip()
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_roundtrip_queue(struct wl_display *display, struct wl_event_queue *queue)
++{
++      struct wl_display *display_wrapper;
++      struct wl_callback *callback;
++      int done, ret = 0;
++
++      done = 0;
++
++      display_wrapper = wl_proxy_create_wrapper(display);
++      if (!display_wrapper)
++              return -1;
++
++      wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
++      callback = wl_display_sync(display_wrapper);
++      wl_proxy_wrapper_destroy(display_wrapper);
++
++      if (callback == NULL)
++              return -1;
++
++      wl_callback_add_listener(callback, &sync_listener, &done);
++      while (!done && ret >= 0)
++              ret = wl_display_dispatch_queue(display, queue);
++
++      if (ret == -1 && !done)
++              wl_callback_destroy(callback);
++
++      return ret;
++}
++
++/** Block until all pending request are processed by the server
++ *
++ * \param display The display context object
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * This function blocks until the server has processed all currently issued
++ * requests by sending a request to the display server and waiting for a reply
++ * before returning.
++ *
++ * This function uses wl_display_dispatch_queue() internally. It is not allowed
++ * to call this function while the thread is being prepared for reading events,
++ * and doing so will cause a dead lock.
++ *
++ * \note This function may dispatch other events being received on the default
++ * queue.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_roundtrip(struct wl_display *display)
++{
++      return wl_display_roundtrip_queue(display, &display->default_queue);
++}
++
++static int
++create_proxies(struct wl_proxy *sender, struct wl_closure *closure)
++{
++      struct wl_proxy *proxy;
++      const char *signature;
++      struct argument_details arg;
++      uint32_t id;
++      int i;
++      int count;
++
++      signature = closure->message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'n':
++                      id = closure->args[i].n;
++                      if (id == 0) {
++                              closure->args[i].o = NULL;
++                              break;
++                      }
++                      proxy = wl_proxy_create_for_id(sender, id,
++                                                     closure->message->types[i]);
++                      if (proxy == NULL)
++                              return -1;
++                      closure->args[i].o = (struct wl_object *)proxy;
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      return 0;
++}
++
++static void
++increase_closure_args_refcount(struct wl_closure *closure)
++{
++      const char *signature;
++      struct argument_details arg;
++      int i, count;
++      struct wl_proxy *proxy;
++
++      signature = closure->message->signature;
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'n':
++              case 'o':
++                      proxy = (struct wl_proxy *) closure->args[i].o;
++                      if (proxy)
++                              proxy->refcount++;
++                      break;
++              default:
++                      break;
++              }
++      }
++
++      closure->proxy->refcount++;
++}
++
++static int
++queue_event(struct wl_display *display, int len)
++{
++      uint32_t p[2], id;
++      int opcode, size;
++      struct wl_proxy *proxy;
++      struct wl_closure *closure;
++      const struct wl_message *message;
++      struct wl_event_queue *queue;
++      struct timespec tp;
++      unsigned int time;
++      int num_zombie_fds;
++
++      wl_connection_copy(display->connection, p, sizeof p);
++      id = p[0];
++      opcode = p[1] & 0xffff;
++      size = p[1] >> 16;
++      if (len < size)
++              return 0;
++
++      /* If our proxy is gone or a zombie, just eat the event (and any FDs,
++       * if applicable). */
++      proxy = wl_map_lookup(&display->objects, id);
++      if (!proxy || wl_object_is_zombie(&display->objects, id)) {
++              struct wl_zombie *zombie = wl_map_lookup(&display->objects, id);
++              num_zombie_fds = (zombie && opcode < zombie->event_count) ?
++                      zombie->fd_count[opcode] : 0;
++
++              if (debug_client) {
++                      clock_gettime(CLOCK_REALTIME, &tp);
++                      time = (tp.tv_sec * 1000000L) + (tp.tv_nsec / 1000);
++
++                      fprintf(stderr, "[%7u.%03u] discarded [%s]@%d.[event %d]"
++                              "(%d fd, %d byte)\n",
++                              time / 1000, time % 1000,
++                              zombie ? "zombie" : "unknown",
++                              id, opcode,
++                              num_zombie_fds, size);
++              }
++              if (num_zombie_fds > 0)
++                      wl_connection_close_fds_in(display->connection,
++                                                 num_zombie_fds);
++
++              wl_connection_consume(display->connection, size);
++              return size;
++      }
++
++      if (opcode >= proxy->object.interface->event_count) {
++              wl_log("interface '%s' has no event %u\n",
++                     proxy->object.interface->name, opcode);
++              return -1;
++      }
++
++      message = &proxy->object.interface->events[opcode];
++      closure = wl_connection_demarshal(display->connection, size,
++                                        &display->objects, message);
++      if (!closure)
++              return -1;
++
++      if (create_proxies(proxy, closure) < 0) {
++              wl_closure_destroy(closure);
++              return -1;
++      }
++
++      if (wl_closure_lookup_objects(closure, &display->objects) != 0) {
++              wl_closure_destroy(closure);
++              return -1;
++      }
++
++      closure->proxy = proxy;
++      increase_closure_args_refcount(closure);
++
++      if (proxy == &display->proxy)
++              queue = &display->display_queue;
++      else
++              queue = proxy->queue;
++
++      wl_list_insert(queue->event_list.prev, &closure->link);
++
++      return size;
++}
++
++static uint32_t
++id_from_object(union wl_argument *arg)
++{
++      struct wl_proxy *proxy;
++
++      if (arg->o) {
++              proxy = (struct wl_proxy *)arg->o;
++              return proxy->object.id;
++      }
++
++      return 0;
++}
++
++static void
++dispatch_event(struct wl_display *display, struct wl_event_queue *queue)
++{
++      struct wl_closure *closure;
++      struct wl_proxy *proxy;
++      int opcode;
++      bool proxy_destroyed;
++
++      closure = wl_container_of(queue->event_list.next, closure, link);
++      wl_list_remove(&closure->link);
++      opcode = closure->opcode;
++
++      /* Verify that the receiving object is still valid by checking if has
++       * been destroyed by the application. */
++      validate_closure_objects(closure);
++      proxy = closure->proxy;
++      proxy_destroyed = !!(proxy->flags & WL_PROXY_FLAG_DESTROYED);
++      if (proxy_destroyed) {
++              if (debug_client)
++                      wl_closure_print(closure, &proxy->object, false, true, id_from_object);
++              destroy_queued_closure(closure);
++              return;
++      }
++
++      pthread_mutex_unlock(&display->mutex);
++
++      if (proxy->dispatcher) {
++              if (debug_client)
++                      wl_closure_print(closure, &proxy->object, false, false, id_from_object);
++
++              wl_closure_dispatch(closure, proxy->dispatcher,
++                                  &proxy->object, opcode);
++      } else if (proxy->object.implementation) {
++              if (debug_client)
++                      wl_closure_print(closure, &proxy->object, false, false, id_from_object);
++
++              wl_closure_invoke(closure, WL_CLOSURE_INVOKE_CLIENT,
++                                &proxy->object, opcode, proxy->user_data);
++      }
++
++      pthread_mutex_lock(&display->mutex);
++
++      destroy_queued_closure(closure);
++}
++
++static int
++read_events(struct wl_display *display)
++{
++      int total, rem, size;
++      uint32_t serial;
++
++      display->reader_count--;
++      if (display->reader_count == 0) {
++              total = wl_connection_read(display->connection);
++              if (total == -1) {
++                      if (errno == EAGAIN) {
++                              /* we must wake up threads whenever
++                               * the reader_count dropped to 0 */
++                              display_wakeup_threads(display);
++
++                              return 0;
++                      }
++
++                      display_fatal_error(display, errno);
++                      return -1;
++              } else if (total == 0) {
++                      /* The compositor has closed the socket. This
++                       * should be considered an error so we'll fake
++                       * an errno */
++                      errno = EPIPE;
++                      display_fatal_error(display, errno);
++                      return -1;
++              }
++
++              for (rem = total; rem >= 8; rem -= size) {
++                      size = queue_event(display, rem);
++                      if (size == -1) {
++                              display_fatal_error(display, errno);
++                              return -1;
++                      } else if (size == 0) {
++                              break;
++                      }
++              }
++
++              display_wakeup_threads(display);
++      } else {
++              serial = display->read_serial;
++              while (display->read_serial == serial)
++                      pthread_cond_wait(&display->reader_cond,
++                                        &display->mutex);
++
++              if (display->last_error) {
++                      errno = display->last_error;
++                      return -1;
++              }
++      }
++
++      return 0;
++}
++
++static void
++cancel_read(struct wl_display *display)
++{
++      display->reader_count--;
++      if (display->reader_count == 0)
++              display_wakeup_threads(display);
++}
++
++/** Read events from display file descriptor
++ *
++ * \param display The display context object
++ * \return 0 on success or -1 on error.  In case of error errno will
++ * be set accordingly
++ *
++ * Calling this function will result in data available on the display file
++ * descriptor being read and read events will be queued on their corresponding
++ * event queues.
++ *
++ * Before calling this function, depending on what thread it is to be called
++ * from, wl_display_prepare_read_queue() or wl_display_prepare_read() needs to
++ * be called. See wl_display_prepare_read_queue() for more details.
++ *
++ * When being called at a point where other threads have been prepared to read
++ * (using wl_display_prepare_read_queue() or wl_display_prepare_read()) this
++ * function will sleep until all other prepared threads have either been
++ * cancelled (using wl_display_cancel_read()) or them self entered this
++ * function. The last thread that calls this function will then read and queue
++ * events on their corresponding event queues, and finally wake up all other
++ * wl_display_read_events() calls causing them to return.
++ *
++ * If a thread cancels a read preparation when all other threads that have
++ * prepared to read has either called wl_display_cancel_read() or
++ * wl_display_read_events(), all reader threads will return without having read
++ * any data.
++ *
++ * To dispatch events that may have been queued, call
++ * wl_display_dispatch_pending() or wl_display_dispatch_queue_pending().
++ *
++ * \sa wl_display_prepare_read(), wl_display_cancel_read(),
++ * wl_display_dispatch_pending(), wl_display_dispatch()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_read_events(struct wl_display *display)
++{
++      int ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      if (display->last_error) {
++              cancel_read(display);
++              pthread_mutex_unlock(&display->mutex);
++
++              errno = display->last_error;
++              return -1;
++      }
++
++      ret = read_events(display);
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++static int
++dispatch_queue(struct wl_display *display, struct wl_event_queue *queue)
++{
++      int count;
++
++      if (display->last_error)
++              goto err;
++
++      count = 0;
++      while (!wl_list_empty(&display->display_queue.event_list)) {
++              dispatch_event(display, &display->display_queue);
++              if (display->last_error)
++                      goto err;
++              count++;
++      }
++
++      while (!wl_list_empty(&queue->event_list)) {
++              dispatch_event(display, queue);
++              if (display->last_error)
++                      goto err;
++              count++;
++      }
++
++      return count;
++
++err:
++      errno = display->last_error;
++
++      return -1;
++}
++
++/** Prepare to read events from the display's file descriptor to a queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to use
++ * \return 0 on success or -1 if event queue was not empty
++ *
++ * This function (or wl_display_prepare_read()) must be called before reading
++ * from the file descriptor using wl_display_read_events(). Calling
++ * wl_display_prepare_read_queue() announces the calling thread's intention to
++ * read and ensures that until the thread is ready to read and calls
++ * wl_display_read_events(), no other thread will read from the file descriptor.
++ * This only succeeds if the event queue is empty, and if not -1 is returned and
++ * errno set to EAGAIN.
++ *
++ * If a thread successfully calls wl_display_prepare_read_queue(), it must
++ * either call wl_display_read_events() when it's ready or cancel the read
++ * intention by calling wl_display_cancel_read().
++ *
++ * Use this function before polling on the display fd or integrate the fd into a
++ * toolkit event loop in a race-free way. A correct usage would be (with most
++ * error checking left out):
++ *
++ * \code
++ * while (wl_display_prepare_read_queue(display, queue) != 0)
++ *         wl_display_dispatch_queue_pending(display, queue);
++ * wl_display_flush(display);
++ *
++ * ret = poll(fds, nfds, -1);
++ * if (has_error(ret))
++ *         wl_display_cancel_read(display);
++ * else
++ *         wl_display_read_events(display);
++ *
++ * wl_display_dispatch_queue_pending(display, queue);
++ * \endcode
++ *
++ * Here we call wl_display_prepare_read_queue(), which ensures that between
++ * returning from that call and eventually calling wl_display_read_events(), no
++ * other thread will read from the fd and queue events in our queue. If the call
++ * to wl_display_prepare_read_queue() fails, we dispatch the pending events and
++ * try again until we're successful.
++ *
++ * The wl_display_prepare_read_queue() function doesn't acquire exclusive access
++ * to the display's fd. It only registers that the thread calling this function
++ * has intention to read from fd. When all registered readers call
++ * wl_display_read_events(), only one (at random) eventually reads and queues
++ * the events and the others are sleeping meanwhile. This way we avoid races and
++ * still can read from more threads.
++ *
++ * \sa wl_display_cancel_read(), wl_display_read_events(),
++ * wl_display_prepare_read()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_prepare_read_queue(struct wl_display *display,
++                            struct wl_event_queue *queue)
++{
++      int ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      if (!wl_list_empty(&queue->event_list)) {
++              errno = EAGAIN;
++              ret = -1;
++      } else {
++              display->reader_count++;
++              ret = 0;
++      }
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++/** Prepare to read events from the display's file descriptor
++ *
++ * \param display The display context object
++ * \return 0 on success or -1 if event queue was not empty
++ *
++ * This function does the same thing as wl_display_prepare_read_queue()
++ * with the default queue passed as the queue.
++ *
++ * \sa wl_display_prepare_read_queue
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_prepare_read(struct wl_display *display)
++{
++      return wl_display_prepare_read_queue(display, &display->default_queue);
++}
++
++/** Cancel read intention on display's fd
++ *
++ * \param display The display context object
++ *
++ * After a thread successfully called wl_display_prepare_read() it must
++ * either call wl_display_read_events() or wl_display_cancel_read().
++ * If the threads do not follow this rule it will lead to deadlock.
++ *
++ * \sa wl_display_prepare_read(), wl_display_read_events()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_cancel_read(struct wl_display *display)
++{
++      pthread_mutex_lock(&display->mutex);
++
++      cancel_read(display);
++
++      pthread_mutex_unlock(&display->mutex);
++}
++
++static int
++wl_display_poll(struct wl_display *display, short int events)
++{
++      int ret;
++      struct pollfd pfd[1];
++
++      pfd[0].fd = display->fd;
++      pfd[0].events = events;
++      do {
++              ret = poll(pfd, 1, -1);
++      } while (ret == -1 && errno == EINTR);
++
++      return ret;
++}
++
++/** Dispatch events in an event queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to dispatch
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch events on the given event queue.
++ *
++ * If the given event queue is empty, this function blocks until there are
++ * events to be read from the display fd. Events are read and queued on
++ * the appropriate event queues. Finally, events on given event queue are
++ * dispatched. On failure -1 is returned and errno set appropriately.
++ *
++ * In a multi threaded environment, do not manually wait using poll() (or
++ * equivalent) before calling this function, as doing so might cause a dead
++ * lock. If external reliance on poll() (or equivalent) is required, see
++ * wl_display_prepare_read_queue() of how to do so.
++ *
++ * This function is thread safe as long as it dispatches the right queue on the
++ * right thread. It is also compatible with the multi thread event reading
++ * preparation API (see wl_display_prepare_read_queue()), and uses the
++ * equivalent functionality internally. It is not allowed to call this function
++ * while the thread is being prepared for reading events, and doing so will
++ * cause a dead lock.
++ *
++ * It can be used as a helper function to ease the procedure of reading and
++ * dispatching events.
++ *
++ * \note Since Wayland 1.5 the display has an extra queue
++ * for its own events (i. e. delete_id). This queue is dispatched always,
++ * no matter what queue we passed as an argument to this function.
++ * That means that this function can return non-0 value even when it
++ * haven't dispatched any event for the given queue.
++ *
++ * \sa wl_display_dispatch(), wl_display_dispatch_pending(),
++ * wl_display_dispatch_queue_pending(), wl_display_prepare_read_queue()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch_queue(struct wl_display *display,
++                        struct wl_event_queue *queue)
++{
++      int ret;
++
++      if (wl_display_prepare_read_queue(display, queue) == -1)
++              return wl_display_dispatch_queue_pending(display, queue);
++
++      while (true) {
++              ret = wl_display_flush(display);
++
++              if (ret != -1 || errno != EAGAIN)
++                      break;
++
++              if (wl_display_poll(display, POLLOUT) == -1) {
++                      wl_display_cancel_read(display);
++                      return -1;
++              }
++      }
++
++      /* Don't stop if flushing hits an EPIPE; continue so we can read any
++       * protocol error that may have triggered it. */
++      if (ret < 0 && errno != EPIPE) {
++              wl_display_cancel_read(display);
++              return -1;
++      }
++
++      if (wl_display_poll(display, POLLIN) == -1) {
++              wl_display_cancel_read(display);
++              return -1;
++      }
++
++      if (wl_display_read_events(display) == -1)
++              return -1;
++
++      return wl_display_dispatch_queue_pending(display, queue);
++}
++
++/** Dispatch pending events in an event queue
++ *
++ * \param display The display context object
++ * \param queue The event queue to dispatch
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch all incoming events for objects assigned to the given
++ * event queue. On failure -1 is returned and errno set appropriately.
++ * If there are no events queued, this function returns immediately.
++ *
++ * \memberof wl_display
++ * \since 1.0.2
++ */
++WL_EXPORT int
++wl_display_dispatch_queue_pending(struct wl_display *display,
++                                struct wl_event_queue *queue)
++{
++      int ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      ret = dispatch_queue(display, queue);
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++/** Process incoming events
++ *
++ * \param display The display context object
++ * \return The number of dispatched events on success or -1 on failure
++ *
++ * Dispatch events on the default event queue.
++ *
++ * If the default event queue is empty, this function blocks until there are
++ * events to be read from the display fd. Events are read and queued on
++ * the appropriate event queues. Finally, events on the default event queue
++ * are dispatched. On failure -1 is returned and errno set appropriately.
++ *
++ * In a multi threaded environment, do not manually wait using poll() (or
++ * equivalent) before calling this function, as doing so might cause a dead
++ * lock. If external reliance on poll() (or equivalent) is required, see
++ * wl_display_prepare_read_queue() of how to do so.
++ *
++ * This function is thread safe as long as it dispatches the right queue on the
++ * right thread. It is also compatible with the multi thread event reading
++ * preparation API (see wl_display_prepare_read_queue()), and uses the
++ * equivalent functionality internally. It is not allowed to call this function
++ * while the thread is being prepared for reading events, and doing so will
++ * cause a dead lock.
++ *
++ * \note It is not possible to check if there are events on the queue
++ * or not. For dispatching default queue events without blocking, see \ref
++ * wl_display_dispatch_pending().
++ *
++ * \sa wl_display_dispatch_pending(), wl_display_dispatch_queue(),
++ * wl_display_read_events()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch(struct wl_display *display)
++{
++      return wl_display_dispatch_queue(display, &display->default_queue);
++}
++
++/** Dispatch default queue events without reading from the display fd
++ *
++ * \param display The display context object
++ * \return The number of dispatched events or -1 on failure
++ *
++ * This function dispatches events on the main event queue. It does not
++ * attempt to read the display fd and simply returns zero if the main
++ * queue is empty, i.e., it doesn't block.
++ *
++ * \sa wl_display_dispatch(), wl_display_dispatch_queue(),
++ * wl_display_flush()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_dispatch_pending(struct wl_display *display)
++{
++      return wl_display_dispatch_queue_pending(display,
++                                               &display->default_queue);
++}
++
++/** Retrieve the last error that occurred on a display
++ *
++ * \param display The display context object
++ * \return The last error that occurred on \c display or 0 if no error occurred
++ *
++ * Return the last error that occurred on the display. This may be an error sent
++ * by the server or caused by the local client.
++ *
++ * \note Errors are \b fatal. If this function returns non-zero the display
++ * can no longer be used.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_get_error(struct wl_display *display)
++{
++      int ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      ret = display->last_error;
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++/** Retrieves the information about a protocol error:
++ *
++ * \param display    The Wayland display
++ * \param interface  if not NULL, stores the interface where the error occurred,
++ *                   or NULL, if unknown.
++ * \param id         if not NULL, stores the object id that generated
++ *                   the error, or 0, if the object id is unknown. There's no
++ *                   guarantee the object is still valid; the client must know
++ *                   if it deleted the object.
++ * \return           The error code as defined in the interface specification.
++ *
++ * \code
++ * int err = wl_display_get_error(display);
++ *
++ * if (err == EPROTO) {
++ *        code = wl_display_get_protocol_error(display, &interface, &id);
++ *        handle_error(code, interface, id);
++ * }
++ *
++ * ...
++ * \endcode
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_get_protocol_error(struct wl_display *display,
++                            const struct wl_interface **interface,
++                            uint32_t *id)
++{
++      uint32_t ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      ret = display->protocol_error.code;
++
++      if (interface)
++              *interface = display->protocol_error.interface;
++      if (id)
++              *id = display->protocol_error.id;
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++
++/** Send all buffered requests on the display to the server
++ *
++ * \param display The display context object
++ * \return The number of bytes sent on success or -1 on failure
++ *
++ * Send all buffered data on the client side to the server. Clients should
++ * always call this function before blocking on input from the display fd.
++ * On success, the number of bytes sent to the server is returned. On
++ * failure, this function returns -1 and errno is set appropriately.
++ *
++ * wl_display_flush() never blocks.  It will write as much data as
++ * possible, but if all data could not be written, errno will be set
++ * to EAGAIN and -1 returned.  In that case, use poll on the display
++ * file descriptor to wait for it to become writable again.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_flush(struct wl_display *display)
++{
++      int ret;
++
++      pthread_mutex_lock(&display->mutex);
++
++      if (display->last_error) {
++              errno = display->last_error;
++              ret = -1;
++      } else {
++              /* We don't make EPIPE a fatal error here, so that we may try to
++               * read events after the failed flush. When the compositor sends
++               * an error it will close the socket, and if we make EPIPE fatal
++               * here we don't get a chance to process the error. */
++              ret = wl_connection_flush(display->connection);
++              if (ret < 0 && errno != EAGAIN && errno != EPIPE)
++                      display_fatal_error(display, errno);
++      }
++
++      pthread_mutex_unlock(&display->mutex);
++
++      return ret;
++}
++
++/** Set the user data associated with a proxy
++ *
++ * \param proxy The proxy object
++ * \param user_data The data to be associated with proxy
++ *
++ * Set the user data associated with \c proxy. When events for this
++ * proxy are received, \c user_data will be supplied to its listener.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
++{
++      proxy->user_data = user_data;
++}
++
++/** Get the user data associated with a proxy
++ *
++ * \param proxy The proxy object
++ * \return The user data associated with proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void *
++wl_proxy_get_user_data(struct wl_proxy *proxy)
++{
++      return proxy->user_data;
++}
++
++/** Get the protocol object version of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The protocol object version of the proxy or 0
++ *
++ * Gets the protocol object version of a proxy object, or 0
++ * if the proxy was created with unversioned API.
++ *
++ * A returned value of 0 means that no version information is
++ * available, so the caller must make safe assumptions about
++ * the object's real version.
++ *
++ * wl_display's version will always return 0.
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT uint32_t
++wl_proxy_get_version(struct wl_proxy *proxy)
++{
++      return proxy->version;
++}
++
++/** Get the id of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The id the object associated with the proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT uint32_t
++wl_proxy_get_id(struct wl_proxy *proxy)
++{
++      return proxy->object.id;
++}
++
++/** Set the tag of a proxy object
++ *
++ * A toolkit or application can set a unique tag on a proxy in order to
++ * identify whether an object is managed by itself or some external part.
++ *
++ * To create a tag, the recommended way is to define a statically allocated
++ * constant char array containing some descriptive string. The tag will be the
++ * pointer to the non-const pointer to the beginning of the array.
++ *
++ * For example, to define and set a tag on a surface managed by a certain
++ * subsystem:
++ *
++ *    static const char *my_tag = "my tag";
++ *
++ *    wl_proxy_set_tag((struct wl_proxy *) surface, &my_tag);
++ *
++ * Then, in a callback with wl_surface as an argument, in order to check
++ * whether it's a surface managed by the same subsystem.
++ *
++ *    const char * const *tag;
++ *
++ *    tag = wl_proxy_get_tag((struct wl_proxy *) surface);
++ *    if (tag != &my_tag)
++ *            return;
++ *
++ *    ...
++ *
++ * For debugging purposes, a tag should be suitable to be included in a debug
++ * log entry, e.g.
++ *
++ *    const char * const *tag;
++ *
++ *    tag = wl_proxy_get_tag((struct wl_proxy *) surface);
++ *    printf("Got a surface with the tag %p (%s)\n",
++ *           tag, (tag && *tag) ? *tag : "");
++ *
++ * \param proxy The proxy object
++ * \param tag The tag
++ *
++ * \memberof wl_proxy
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_proxy_set_tag(struct wl_proxy *proxy,
++               const char * const *tag)
++{
++      proxy->tag = tag;
++}
++
++/** Get the tag of a proxy object
++ *
++ * See wl_proxy_set_tag for details.
++ *
++ * \param proxy The proxy object
++ *
++ * \memberof wl_proxy
++ * \since 1.17.90
++ */
++WL_EXPORT const char * const *
++wl_proxy_get_tag(struct wl_proxy *proxy)
++{
++      return proxy->tag;
++}
++
++/** Get the interface name (class) of a proxy object
++ *
++ * \param proxy The proxy object
++ * \return The interface name of the object associated with the proxy
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT const char *
++wl_proxy_get_class(struct wl_proxy *proxy)
++{
++      return proxy->object.interface->name;
++}
++
++/** Assign a proxy to an event queue
++ *
++ * \param proxy The proxy object
++ * \param queue The event queue that will handle this proxy or NULL
++ *
++ * Assign proxy to event queue. Events coming from \c proxy will be
++ * queued in \c queue from now. If queue is NULL, then the display's
++ * default queue is set to the proxy.
++ *
++ * In order to guarantee proper handing of all events which were queued
++ * before the queue change takes effect, it is required to dispatch the
++ * proxy's old event queue after setting a new event queue.
++ *
++ * This is particularly important for multi-threaded setups, where it is
++ * possible for events to be queued to the proxy's old queue from a
++ * different thread during the invocation of this function.
++ *
++ * To ensure that all events for a newly created proxy are dispatched
++ * on a particular queue, it is necessary to use a proxy wrapper if
++ * events are read and dispatched on more than one thread. See
++ * wl_proxy_create_wrapper() for more details.
++ *
++ * \note By default, the queue set in proxy is the one inherited from parent.
++ *
++ * \sa wl_display_dispatch_queue()
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue)
++{
++      pthread_mutex_lock(&proxy->display->mutex);
++
++      if (queue) {
++              assert(proxy->display == queue->display);
++              proxy->queue = queue;
++      } else {
++              proxy->queue = &proxy->display->default_queue;
++      }
++
++      pthread_mutex_unlock(&proxy->display->mutex);
++}
++
++/** Create a proxy wrapper for making queue assignments thread-safe
++ *
++ * \param proxy The proxy object to be wrapped
++ * \return A proxy wrapper for the given proxy or NULL on failure
++ *
++ * A proxy wrapper is type of 'struct wl_proxy' instance that can be used when
++ * sending requests instead of using the original proxy. A proxy wrapper does
++ * not have an implementation or dispatcher, and events received on the
++ * object is still emitted on the original proxy. Trying to set an
++ * implementation or dispatcher will have no effect but result in a warning
++ * being logged.
++ *
++ * Setting the proxy queue of the proxy wrapper will make new objects created
++ * using the proxy wrapper use the set proxy queue.
++ * Even though there is no implementation nor dispatcher, the proxy queue can
++ * be changed. This will affect the default queue of new objects created by
++ * requests sent via the proxy wrapper.
++ *
++ * A proxy wrapper can only be destroyed using wl_proxy_wrapper_destroy().
++ *
++ * A proxy wrapper must be destroyed before the proxy it was created from.
++ *
++ * If a user reads and dispatches events on more than one thread, it is
++ * necessary to use a proxy wrapper when sending requests on objects when the
++ * intention is that a newly created proxy is to use a proxy queue different
++ * from the proxy the request was sent on, as creating the new proxy and then
++ * setting the queue is not thread safe.
++ *
++ * For example, a module that runs using its own proxy queue that needs to
++ * do display roundtrip must wrap the wl_display proxy object before sending
++ * the wl_display.sync request. For example:
++ *
++ * \code
++ *
++ *   struct wl_event_queue *queue = ...;
++ *   struct wl_display *wrapped_display;
++ *   struct wl_callback *callback;
++ *
++ *   wrapped_display = wl_proxy_create_wrapper(display);
++ *   wl_proxy_set_queue((struct wl_proxy *) wrapped_display, queue);
++ *   callback = wl_display_sync(wrapped_display);
++ *   wl_proxy_wrapper_destroy(wrapped_display);
++ *   wl_callback_add_listener(callback, ...);
++ *
++ * \endcode
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void *
++wl_proxy_create_wrapper(void *proxy)
++{
++      struct wl_proxy *wrapped_proxy = proxy;
++      struct wl_proxy *wrapper;
++
++      wrapper = zalloc(sizeof *wrapper);
++      if (!wrapper)
++              return NULL;
++
++      pthread_mutex_lock(&wrapped_proxy->display->mutex);
++
++      wrapper->object.interface = wrapped_proxy->object.interface;
++      wrapper->object.id = wrapped_proxy->object.id;
++      wrapper->version = wrapped_proxy->version;
++      wrapper->display = wrapped_proxy->display;
++      wrapper->queue = wrapped_proxy->queue;
++      wrapper->flags = WL_PROXY_FLAG_WRAPPER;
++      wrapper->refcount = 1;
++
++      pthread_mutex_unlock(&wrapped_proxy->display->mutex);
++
++      return wrapper;
++}
++
++/** Destroy a proxy wrapper
++ * \param proxy_wrapper The proxy wrapper to be destroyed
++ *
++ * \memberof wl_proxy
++ */
++WL_EXPORT void
++wl_proxy_wrapper_destroy(void *proxy_wrapper)
++{
++      struct wl_proxy *wrapper = proxy_wrapper;
++
++      if (!(wrapper->flags & WL_PROXY_FLAG_WRAPPER))
++              wl_abort("Tried to destroy non-wrapper proxy with "
++                       "wl_proxy_wrapper_destroy\n");
++
++      assert(wrapper->refcount == 1);
++
++      free(wrapper);
++}
++
++WL_EXPORT void
++wl_log_set_handler_client(wl_log_func_t handler)
++{
++      wl_log_handler = handler;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9f70fa3fbb1fc01d5603d851e3413e83e112b994
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,42 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file
++ *
++ *  \brief Include the client API and protocol C API.
++ *
++ *  \warning Use of this header file is discouraged. Prefer including
++ *  wayland-client-core.h instead, which does not include the
++ *  client protocol header and as such only defines the library
++ *  API.
++ */
++
++#ifndef WAYLAND_CLIENT_H
++#define WAYLAND_CLIENT_H
++
++#include "wayland-client-core.h"
++#include "wayland-client-protocol.h"
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a9066cae9c93b607ea92ad1da1746f3b37a2bcb3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,252 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include "../config.h"
++
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <fcntl.h>
++#include <errno.h>
++#include <string.h>
++#include <sys/epoll.h>
++#include <sys/mman.h>
++#include <sys/un.h>
++#ifdef HAVE_SYS_UCRED_H
++#include <sys/ucred.h>
++#endif
++
++#include "wayland-os.h"
++
++static int
++set_cloexec_or_close(int fd)
++{
++      long flags;
++
++      if (fd == -1)
++              return -1;
++
++      flags = fcntl(fd, F_GETFD);
++      if (flags == -1)
++              goto err;
++
++      if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
++              goto err;
++
++      return fd;
++
++err:
++      close(fd);
++      return -1;
++}
++
++int
++wl_os_socket_cloexec(int domain, int type, int protocol)
++{
++      int fd;
++
++      fd = socket(domain, type | SOCK_CLOEXEC, protocol);
++      if (fd >= 0)
++              return fd;
++      if (errno != EINVAL)
++              return -1;
++
++      fd = socket(domain, type, protocol);
++      return set_cloexec_or_close(fd);
++}
++
++#if defined(__FreeBSD__)
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
++{
++      socklen_t len;
++      struct xucred ucred;
++
++      len = sizeof(ucred);
++      if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &ucred, &len) < 0 ||
++          ucred.cr_version != XUCRED_VERSION)
++              return -1;
++      *uid = ucred.cr_uid;
++      *gid = ucred.cr_gid;
++#if HAVE_XUCRED_CR_PID
++      /* Since https://cgit.freebsd.org/src/commit/?id=c5afec6e895a */
++      *pid = ucred.cr_pid;
++#else
++      *pid = 0;
++#endif
++      return 0;
++}
++#elif defined(SO_PEERCRED)
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid)
++{
++      socklen_t len;
++      struct ucred ucred;
++
++      len = sizeof(ucred);
++      if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0)
++              return -1;
++      *uid = ucred.uid;
++      *gid = ucred.gid;
++      *pid = ucred.pid;
++      return 0;
++}
++#else
++#error "Don't know how to read ucred on this platform"
++#endif
++
++int
++wl_os_dupfd_cloexec(int fd, int minfd)
++{
++      int newfd;
++
++      newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
++      if (newfd >= 0)
++              return newfd;
++      if (errno != EINVAL)
++              return -1;
++
++      newfd = fcntl(fd, F_DUPFD, minfd);
++      return set_cloexec_or_close(newfd);
++}
++
++static ssize_t
++recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
++{
++      ssize_t len;
++      struct cmsghdr *cmsg;
++      unsigned char *data;
++      int *fd;
++      int *end;
++
++      len = recvmsg(sockfd, msg, flags);
++      if (len == -1)
++              return -1;
++
++      if (!msg->msg_control || msg->msg_controllen == 0)
++              return len;
++
++      cmsg = CMSG_FIRSTHDR(msg);
++      for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
++              if (cmsg->cmsg_level != SOL_SOCKET ||
++                  cmsg->cmsg_type != SCM_RIGHTS)
++                      continue;
++
++              data = CMSG_DATA(cmsg);
++              end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0));
++              for (fd = (int *)data; fd < end; ++fd)
++                      *fd = set_cloexec_or_close(*fd);
++      }
++
++      return len;
++}
++
++ssize_t
++wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
++{
++#if HAVE_BROKEN_MSG_CMSG_CLOEXEC
++      /*
++       * FreeBSD had a broken implementation of MSG_CMSG_CLOEXEC between 2015
++       * and 2021, so we have to use the non-MSG_CMSG_CLOEXEC fallback
++       * directly when compiling against a version that does not include the
++       * fix (https://cgit.freebsd.org/src/commit/?id=6ceacebdf52211).
++       */
++#pragma message("Using fallback directly since MSG_CMSG_CLOEXEC is broken.")
++#else
++      ssize_t len;
++
++      len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
++      if (len >= 0)
++              return len;
++      if (errno != EINVAL)
++              return -1;
++#endif
++      return recvmsg_cloexec_fallback(sockfd, msg, flags);
++}
++
++int
++wl_os_epoll_create_cloexec(void)
++{
++      int fd;
++
++#ifdef EPOLL_CLOEXEC
++      fd = epoll_create1(EPOLL_CLOEXEC);
++      if (fd >= 0)
++              return fd;
++      if (errno != EINVAL)
++              return -1;
++#endif
++
++      fd = epoll_create(1);
++      return set_cloexec_or_close(fd);
++}
++
++int
++wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen)
++{
++      int fd;
++
++#ifdef HAVE_ACCEPT4
++      fd = accept4(sockfd, addr, addrlen, SOCK_CLOEXEC);
++      if (fd >= 0)
++              return fd;
++      if (errno != ENOSYS)
++              return -1;
++#endif
++
++      fd = accept(sockfd, addr, addrlen);
++      return set_cloexec_or_close(fd);
++}
++
++/*
++ * Fallback function for operating systems that don't implement
++ * mremap(MREMAP_MAYMOVE).
++ */
++void *
++wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size,
++                   ssize_t new_size, int prot, int flags)
++{
++      void *result;
++
++      /* Make sure any pending write is flushed. */
++      if (msync(old_data, *old_size, MS_SYNC) != 0)
++              return MAP_FAILED;
++
++      /* We could try mapping a new block immediately after the current one
++       * with MAP_FIXED, however that is not guaranteed to work and breaks
++       * on CHERI-enabled architectures since the data pointer will still
++       * have the bounds of the previous allocation.
++       */
++      result = mmap(NULL, new_size, prot, flags, fd, 0);
++      if (result == MAP_FAILED)
++              return MAP_FAILED;
++
++      if (munmap(old_data, *old_size) == 0)
++              *old_size = 0;
++
++      return result;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..068fd2fea3da8e0a13a3ab993fcc7d4c609a366d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,76 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_OS_H
++#define WAYLAND_OS_H
++
++#include <sys/types.h>
++#include <sys/socket.h>
++
++int
++wl_os_socket_cloexec(int domain, int type, int protocol);
++
++int
++wl_os_socket_peercred(int sockfd, uid_t *uid, gid_t *gid, pid_t *pid);
++
++int
++wl_os_dupfd_cloexec(int fd, int minfd);
++
++ssize_t
++wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags);
++
++int
++wl_os_epoll_create_cloexec(void);
++
++int
++wl_os_accept_cloexec(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
++
++void *
++wl_os_mremap_maymove(int fd, void *old_data, ssize_t *old_size,
++                   ssize_t new_size, int prot, int flags);
++
++
++/*
++ * The following are for wayland-os.c and the unit tests.
++ * Do not use them elsewhere.
++ */
++
++#ifdef __linux__
++
++#ifndef SOCK_CLOEXEC
++#define SOCK_CLOEXEC 02000000
++#endif
++
++#ifndef F_DUPFD_CLOEXEC
++#define F_DUPFD_CLOEXEC 1030
++#endif
++
++#ifndef MSG_CMSG_CLOEXEC
++#define MSG_CMSG_CLOEXEC 0x40000000
++#endif
++
++#endif /* __linux__ */
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9274f1b83c527e7d5a386e145847f156f8c97cfe
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,240 @@@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_PRIVATE_H
++#define WAYLAND_PRIVATE_H
++
++#include <stdarg.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdbool.h>
++
++#define WL_HIDE_DEPRECATED 1
++
++#include "wayland-util.h"
++
++/* Invalid memory address */
++#define WL_ARRAY_POISON_PTR (void *) 4
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++#define WL_MAP_SERVER_SIDE 0
++#define WL_MAP_CLIENT_SIDE 1
++#define WL_SERVER_ID_START 0xff000000
++#define WL_MAP_MAX_OBJECTS 0x00f00000
++#define WL_CLOSURE_MAX_ARGS 20
++
++struct wl_object {
++      const struct wl_interface *interface;
++      const void *implementation;
++      uint32_t id;
++};
++
++int
++wl_interface_equal(const struct wl_interface *iface1,
++                 const struct wl_interface *iface2);
++
++/* Flags for wl_map_insert_new and wl_map_insert_at.  Flags can be queried with
++ * wl_map_lookup_flags.  The current implementation has room for 1 bit worth of
++ * flags.  If more flags are ever added, the implementation of wl_map will have
++ * to change to allow for new flags */
++enum wl_map_entry_flags {
++      WL_MAP_ENTRY_LEGACY = (1 << 0), /* Server side only */
++      WL_MAP_ENTRY_ZOMBIE = (1 << 0) /* Client side only */
++};
++
++struct wl_map {
++      struct wl_array client_entries;
++      struct wl_array server_entries;
++      uint32_t side;
++      uint32_t free_list;
++};
++
++typedef enum wl_iterator_result (*wl_iterator_func_t)(void *element,
++                                                    void *data,
++                                                    uint32_t flags);
++
++void
++wl_map_init(struct wl_map *map, uint32_t side);
++
++void
++wl_map_release(struct wl_map *map);
++
++uint32_t
++wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data);
++
++int
++wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data);
++
++int
++wl_map_reserve_new(struct wl_map *map, uint32_t i);
++
++void
++wl_map_remove(struct wl_map *map, uint32_t i);
++
++void *
++wl_map_lookup(struct wl_map *map, uint32_t i);
++
++uint32_t
++wl_map_lookup_flags(struct wl_map *map, uint32_t i);
++
++void
++wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data);
++
++struct wl_connection *
++wl_connection_create(int fd);
++
++int
++wl_connection_destroy(struct wl_connection *connection);
++
++void
++wl_connection_copy(struct wl_connection *connection, void *data, size_t size);
++
++void
++wl_connection_consume(struct wl_connection *connection, size_t size);
++
++int
++wl_connection_flush(struct wl_connection *connection);
++
++uint32_t
++wl_connection_pending_input(struct wl_connection *connection);
++
++int
++wl_connection_read(struct wl_connection *connection);
++
++int
++wl_connection_write(struct wl_connection *connection,
++                  const void *data, size_t count);
++
++int
++wl_connection_queue(struct wl_connection *connection,
++                  const void *data, size_t count);
++
++int
++wl_connection_get_fd(struct wl_connection *connection);
++
++struct wl_closure {
++      int count;
++      const struct wl_message *message;
++      uint32_t opcode;
++      uint32_t sender_id;
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      struct wl_list link;
++      struct wl_proxy *proxy;
++      struct wl_array extra[0];
++};
++
++struct argument_details {
++      char type;
++      int nullable;
++};
++
++const char *
++get_next_argument(const char *signature, struct argument_details *details);
++
++int
++arg_count_for_signature(const char *signature);
++
++int
++wl_message_count_arrays(const struct wl_message *message);
++
++int
++wl_message_get_since(const struct wl_message *message);
++
++void
++wl_argument_from_va_list(const char *signature, union wl_argument *args,
++                       int count, va_list ap);
++
++struct wl_closure *
++wl_closure_marshal(struct wl_object *sender,
++                  uint32_t opcode, union wl_argument *args,
++                  const struct wl_message *message);
++
++struct wl_closure *
++wl_closure_vmarshal(struct wl_object *sender,
++                  uint32_t opcode, va_list ap,
++                  const struct wl_message *message);
++
++struct wl_closure *
++wl_connection_demarshal(struct wl_connection *connection,
++                      uint32_t size,
++                      struct wl_map *objects,
++                      const struct wl_message *message);
++
++bool
++wl_object_is_zombie(struct wl_map *map, uint32_t id);
++
++int
++wl_closure_lookup_objects(struct wl_closure *closure, struct wl_map *objects);
++
++enum wl_closure_invoke_flag {
++      WL_CLOSURE_INVOKE_CLIENT = (1 << 0),
++      WL_CLOSURE_INVOKE_SERVER = (1 << 1)
++};
++
++void
++wl_closure_invoke(struct wl_closure *closure, uint32_t flags,
++                struct wl_object *target, uint32_t opcode, void *data);
++
++void
++wl_closure_dispatch(struct wl_closure *closure, wl_dispatcher_func_t dispatcher,
++                  struct wl_object *target, uint32_t opcode);
++
++int
++wl_closure_send(struct wl_closure *closure, struct wl_connection *connection);
++
++int
++wl_closure_queue(struct wl_closure *closure, struct wl_connection *connection);
++
++void
++wl_closure_print(struct wl_closure *closure,
++               struct wl_object *target, int send, int discarded,
++               uint32_t (*n_parse)(union wl_argument *arg));
++
++void
++wl_closure_destroy(struct wl_closure *closure);
++
++extern wl_log_func_t wl_log_handler;
++
++void wl_log(const char *fmt, ...);
++void wl_abort(const char *fmt, ...);
++
++struct wl_display;
++
++struct wl_array *
++wl_display_get_additional_shm_formats(struct wl_display *display);
++
++static inline void *
++zalloc(size_t s)
++{
++      return calloc(1, s);
++}
++
++void
++wl_connection_close_fds_in(struct wl_connection *connection, int max);
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7a1375f80cb21f0889f5816f01f67da2d523477d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,684 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_SERVER_CORE_H
++#define WAYLAND_SERVER_CORE_H
++
++#include <sys/types.h>
++#include <stdint.h>
++#include <stdbool.h>
++#include "wayland-util.h"
++#include "wayland-version.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++enum {
++      WL_EVENT_READABLE = 0x01,
++      WL_EVENT_WRITABLE = 0x02,
++      WL_EVENT_HANGUP   = 0x04,
++      WL_EVENT_ERROR    = 0x08
++};
++
++/** File descriptor dispatch function type
++ *
++ * Functions of this type are used as callbacks for file descriptor events.
++ *
++ * \param fd The file descriptor delivering the event.
++ * \param mask Describes the kind of the event as a bitwise-or of:
++ * \c WL_EVENT_READABLE, \c WL_EVENT_WRITABLE, \c WL_EVENT_HANGUP,
++ * \c WL_EVENT_ERROR.
++ * \param data The user data argument of the related wl_event_loop_add_fd()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_fd()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_fd_func_t)(int fd, uint32_t mask, void *data);
++
++/** Timer dispatch function type
++ *
++ * Functions of this type are used as callbacks for timer expiry.
++ *
++ * \param data The user data argument of the related wl_event_loop_add_timer()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_timer()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_timer_func_t)(void *data);
++
++/** Signal dispatch function type
++ *
++ * Functions of this type are used as callbacks for (POSIX) signals.
++ *
++ * \param signal_number
++ * \param data The user data argument of the related wl_event_loop_add_signal()
++ * call.
++ * \return If the event source is registered for re-check with
++ * wl_event_source_check(): 0 for all done, 1 for needing a re-check.
++ * If not registered, the return value is ignored and should be zero.
++ *
++ * \sa wl_event_loop_add_signal()
++ * \memberof wl_event_source
++ */
++typedef int (*wl_event_loop_signal_func_t)(int signal_number, void *data);
++
++/** Idle task function type
++ *
++ * Functions of this type are used as callbacks before blocking in
++ * wl_event_loop_dispatch().
++ *
++ * \param data The user data argument of the related wl_event_loop_add_idle()
++ * call.
++ *
++ * \sa wl_event_loop_add_idle() wl_event_loop_dispatch()
++ * \memberof wl_event_source
++ */
++typedef void (*wl_event_loop_idle_func_t)(void *data);
++
++/** \struct wl_event_loop
++ *
++ * \brief An event loop context
++ *
++ * Usually you create an event loop context, add sources to it, and call
++ * wl_event_loop_dispatch() in a loop to process events.
++ *
++ * \sa wl_event_source
++ */
++
++/** \struct wl_event_source
++ *
++ * \brief An abstract event source
++ *
++ * This is the generic type for fd, timer, signal, and idle sources.
++ * Functions that operate on specific source types must not be used with
++ * a different type, even if the function signature allows it.
++ */
++
++struct wl_event_loop *
++wl_event_loop_create(void);
++
++void
++wl_event_loop_destroy(struct wl_event_loop *loop);
++
++struct wl_event_source *
++wl_event_loop_add_fd(struct wl_event_loop *loop,
++                   int fd, uint32_t mask,
++                   wl_event_loop_fd_func_t func,
++                   void *data);
++
++int
++wl_event_source_fd_update(struct wl_event_source *source, uint32_t mask);
++
++struct wl_event_source *
++wl_event_loop_add_timer(struct wl_event_loop *loop,
++                      wl_event_loop_timer_func_t func,
++                      void *data);
++
++struct wl_event_source *
++wl_event_loop_add_signal(struct wl_event_loop *loop,
++                       int signal_number,
++                       wl_event_loop_signal_func_t func,
++                       void *data);
++
++int
++wl_event_source_timer_update(struct wl_event_source *source,
++                           int ms_delay);
++
++int
++wl_event_source_remove(struct wl_event_source *source);
++
++void
++wl_event_source_check(struct wl_event_source *source);
++
++int
++wl_event_loop_dispatch(struct wl_event_loop *loop, int timeout);
++
++void
++wl_event_loop_dispatch_idle(struct wl_event_loop *loop);
++
++struct wl_event_source *
++wl_event_loop_add_idle(struct wl_event_loop *loop,
++                     wl_event_loop_idle_func_t func,
++                     void *data);
++
++int
++wl_event_loop_get_fd(struct wl_event_loop *loop);
++
++struct wl_listener;
++
++typedef void (*wl_notify_func_t)(struct wl_listener *listener, void *data);
++
++void
++wl_event_loop_add_destroy_listener(struct wl_event_loop *loop,
++                                 struct wl_listener *listener);
++
++struct wl_listener *
++wl_event_loop_get_destroy_listener(struct wl_event_loop *loop,
++                                 wl_notify_func_t notify);
++
++struct wl_display *
++wl_display_create(void);
++
++void
++wl_display_destroy(struct wl_display *display);
++
++struct wl_event_loop *
++wl_display_get_event_loop(struct wl_display *display);
++
++int
++wl_display_add_socket(struct wl_display *display, const char *name);
++
++const char *
++wl_display_add_socket_auto(struct wl_display *display);
++
++int
++wl_display_add_socket_fd(struct wl_display *display, int sock_fd);
++
++void
++wl_display_terminate(struct wl_display *display);
++
++void
++wl_display_run(struct wl_display *display);
++
++void
++wl_display_flush_clients(struct wl_display *display);
++
++void
++wl_display_destroy_clients(struct wl_display *display);
++
++struct wl_client;
++
++typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
++                                    uint32_t version, uint32_t id);
++
++uint32_t
++wl_display_get_serial(struct wl_display *display);
++
++uint32_t
++wl_display_next_serial(struct wl_display *display);
++
++void
++wl_display_add_destroy_listener(struct wl_display *display,
++                              struct wl_listener *listener);
++
++void
++wl_display_add_client_created_listener(struct wl_display *display,
++                                      struct wl_listener *listener);
++
++struct wl_listener *
++wl_display_get_destroy_listener(struct wl_display *display,
++                              wl_notify_func_t notify);
++
++struct wl_global *
++wl_global_create(struct wl_display *display,
++               const struct wl_interface *interface,
++               int version,
++               void *data, wl_global_bind_func_t bind);
++
++void
++wl_global_remove(struct wl_global *global);
++
++void
++wl_global_destroy(struct wl_global *global);
++
++/** A filter function for wl_global objects
++ *
++ * \param client The client object
++ * \param global The global object to show or hide
++ * \param data   The user data pointer
++ *
++ * A filter function enables the server to decide which globals to
++ * advertise to each client.
++ *
++ * When a wl_global filter is set, the given callback function will be
++ * called during wl_global advertisement and binding.
++ *
++ * This function should return true if the global object should be made
++ * visible to the client or false otherwise.
++ */
++typedef bool (*wl_display_global_filter_func_t)(const struct wl_client *client,
++                                              const struct wl_global *global,
++                                              void *data);
++
++void
++wl_display_set_global_filter(struct wl_display *display,
++                           wl_display_global_filter_func_t filter,
++                           void *data);
++
++const struct wl_interface *
++wl_global_get_interface(const struct wl_global *global);
++
++uint32_t
++wl_global_get_version(const struct wl_global *global);
++
++struct wl_display *
++wl_global_get_display(const struct wl_global *global);
++
++void *
++wl_global_get_user_data(const struct wl_global *global);
++
++void
++wl_global_set_user_data(struct wl_global *global, void *data);
++
++struct wl_client *
++wl_client_create(struct wl_display *display, int fd);
++
++struct wl_list *
++wl_display_get_client_list(struct wl_display *display);
++
++struct wl_list *
++wl_client_get_link(struct wl_client *client);
++
++struct wl_client *
++wl_client_from_link(struct wl_list *link);
++
++/** Iterate over a list of clients. */
++#define wl_client_for_each(client, list)                              \
++      for (client = wl_client_from_link((list)->next);        \
++           wl_client_get_link(client) != (list);                      \
++           client = wl_client_from_link(wl_client_get_link(client)->next))
++
++void
++wl_client_destroy(struct wl_client *client);
++
++void
++wl_client_flush(struct wl_client *client);
++
++void
++wl_client_get_credentials(struct wl_client *client,
++                        pid_t *pid, uid_t *uid, gid_t *gid);
++
++int
++wl_client_get_fd(struct wl_client *client);
++
++void
++wl_client_add_destroy_listener(struct wl_client *client,
++                             struct wl_listener *listener);
++
++struct wl_listener *
++wl_client_get_destroy_listener(struct wl_client *client,
++                             wl_notify_func_t notify);
++
++struct wl_resource *
++wl_client_get_object(struct wl_client *client, uint32_t id);
++
++void
++wl_client_post_no_memory(struct wl_client *client);
++
++void
++wl_client_post_implementation_error(struct wl_client *client,
++                                    const char* msg, ...) WL_PRINTF(2,3);
++
++void
++wl_client_add_resource_created_listener(struct wl_client *client,
++                                        struct wl_listener *listener);
++
++typedef enum wl_iterator_result (*wl_client_for_each_resource_iterator_func_t)(
++                                              struct wl_resource *resource,
++                                              void *user_data);
++
++void
++wl_client_for_each_resource(struct wl_client *client,
++                            wl_client_for_each_resource_iterator_func_t iterator,
++                            void *user_data);
++
++/** \class wl_listener
++ *
++ * \brief A single listener for Wayland signals
++ *
++ * wl_listener provides the means to listen for wl_signal notifications. Many
++ * Wayland objects use wl_listener for notification of significant events like
++ * object destruction.
++ *
++ * Clients should create wl_listener objects manually and can register them as
++ * listeners to signals using #wl_signal_add, assuming the signal is
++ * directly accessible. For opaque structs like wl_event_loop, adding a
++ * listener should be done through provided accessor methods. A listener can
++ * only listen to one signal at a time.
++ *
++ * \code
++ * struct wl_listener your_listener;
++ *
++ * your_listener.notify = your_callback_method;
++ *
++ * // Direct access
++ * wl_signal_add(&some_object->destroy_signal, &your_listener);
++ *
++ * // Accessor access
++ * wl_event_loop *loop = ...;
++ * wl_event_loop_add_destroy_listener(loop, &your_listener);
++ * \endcode
++ *
++ * If the listener is part of a larger struct, #wl_container_of can be used
++ * to retrieve a pointer to it:
++ *
++ * \code
++ * void your_listener(struct wl_listener *listener, void *data)
++ * {
++ *    struct your_data *data;
++ *
++ *    your_data = wl_container_of(listener, data, your_member_name);
++ * }
++ * \endcode
++ *
++ * If you need to remove a listener from a signal, use wl_list_remove().
++ *
++ * \code
++ * wl_list_remove(&your_listener.link);
++ * \endcode
++ *
++ * \sa wl_signal
++ */
++struct wl_listener {
++      struct wl_list link;
++      wl_notify_func_t notify;
++};
++
++/** \class wl_signal
++ *
++ * \brief A source of a type of observable event
++ *
++ * Signals are recognized points where significant events can be observed.
++ * Compositors as well as the server can provide signals. Observers are
++ * wl_listener's that are added through #wl_signal_add. Signals are emitted
++ * using #wl_signal_emit, which will invoke all listeners until that
++ * listener is removed by wl_list_remove() (or whenever the signal is
++ * destroyed).
++ *
++ * \sa wl_listener for more information on using wl_signal
++ */
++struct wl_signal {
++      struct wl_list listener_list;
++};
++
++/** Initialize a new \ref wl_signal for use.
++ *
++ * \param signal The signal that will be initialized
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_init(struct wl_signal *signal)
++{
++      wl_list_init(&signal->listener_list);
++}
++
++/** Add the specified listener to this signal.
++ *
++ * \param signal The signal that will emit events to the listener
++ * \param listener The listener to add
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_add(struct wl_signal *signal, struct wl_listener *listener)
++{
++      wl_list_insert(signal->listener_list.prev, &listener->link);
++}
++
++/** Gets the listener struct for the specified callback.
++ *
++ * \param signal The signal that contains the specified listener
++ * \param notify The listener that is the target of this search
++ * \return the list item that corresponds to the specified listener, or NULL
++ * if none was found
++ *
++ * \memberof wl_signal
++ */
++static inline struct wl_listener *
++wl_signal_get(struct wl_signal *signal, wl_notify_func_t notify)
++{
++      struct wl_listener *l;
++
++      wl_list_for_each(l, &signal->listener_list, link)
++              if (l->notify == notify)
++                      return l;
++
++      return NULL;
++}
++
++/** Emits this signal, notifying all registered listeners.
++ *
++ * \param signal The signal object that will emit the signal
++ * \param data The data that will be emitted with the signal
++ *
++ * \memberof wl_signal
++ */
++static inline void
++wl_signal_emit(struct wl_signal *signal, void *data)
++{
++      struct wl_listener *l, *next;
++
++      wl_list_for_each_safe(l, next, &signal->listener_list, link)
++              l->notify(l, data);
++}
++
++void
++wl_signal_emit_mutable(struct wl_signal *signal, void *data);
++
++typedef void (*wl_resource_destroy_func_t)(struct wl_resource *resource);
++
++/*
++ * Post an event to the client's object referred to by 'resource'.
++ * 'opcode' is the event number generated from the protocol XML
++ * description (the event name). The variable arguments are the event
++ * parameters, in the order they appear in the protocol XML specification.
++ *
++ * The variable arguments' types are:
++ * - type=uint:       uint32_t
++ * - type=int:                int32_t
++ * - type=fixed:      wl_fixed_t
++ * - type=string:     (const char *) to a nil-terminated string
++ * - type=array:      (struct wl_array *)
++ * - type=fd:         int, that is an open file descriptor
++ * - type=new_id:     (struct wl_object *) or (struct wl_resource *)
++ * - type=object:     (struct wl_object *) or (struct wl_resource *)
++ */
++void
++wl_resource_post_event(struct wl_resource *resource,
++                     uint32_t opcode, ...);
++
++void
++wl_resource_post_event_array(struct wl_resource *resource,
++                           uint32_t opcode, union wl_argument *args);
++
++void
++wl_resource_queue_event(struct wl_resource *resource,
++                      uint32_t opcode, ...);
++
++void
++wl_resource_queue_event_array(struct wl_resource *resource,
++                            uint32_t opcode, union wl_argument *args);
++
++/* msg is a printf format string, variable args are its args. */
++void
++wl_resource_post_error(struct wl_resource *resource,
++                     uint32_t code, const char *msg, ...) WL_PRINTF(3, 4);
++
++void
++wl_resource_post_no_memory(struct wl_resource *resource);
++
++struct wl_display *
++wl_client_get_display(struct wl_client *client);
++
++struct wl_resource *
++wl_resource_create(struct wl_client *client,
++                 const struct wl_interface *interface,
++                 int version, uint32_t id);
++
++void
++wl_resource_set_implementation(struct wl_resource *resource,
++                             const void *implementation,
++                             void *data,
++                             wl_resource_destroy_func_t destroy);
++
++void
++wl_resource_set_dispatcher(struct wl_resource *resource,
++                         wl_dispatcher_func_t dispatcher,
++                         const void *implementation,
++                         void *data,
++                         wl_resource_destroy_func_t destroy);
++
++void
++wl_resource_destroy(struct wl_resource *resource);
++
++uint32_t
++wl_resource_get_id(struct wl_resource *resource);
++
++struct wl_list *
++wl_resource_get_link(struct wl_resource *resource);
++
++struct wl_resource *
++wl_resource_from_link(struct wl_list *resource);
++
++struct wl_resource *
++wl_resource_find_for_client(struct wl_list *list, struct wl_client *client);
++
++struct wl_client *
++wl_resource_get_client(struct wl_resource *resource);
++
++void
++wl_resource_set_user_data(struct wl_resource *resource, void *data);
++
++void *
++wl_resource_get_user_data(struct wl_resource *resource);
++
++int
++wl_resource_get_version(struct wl_resource *resource);
++
++void
++wl_resource_set_destructor(struct wl_resource *resource,
++                         wl_resource_destroy_func_t destroy);
++
++int
++wl_resource_instance_of(struct wl_resource *resource,
++                      const struct wl_interface *interface,
++                      const void *implementation);
++const char *
++wl_resource_get_class(struct wl_resource *resource);
++
++void
++wl_resource_add_destroy_listener(struct wl_resource *resource,
++                               struct wl_listener *listener);
++
++struct wl_listener *
++wl_resource_get_destroy_listener(struct wl_resource *resource,
++                               wl_notify_func_t notify);
++
++#define wl_resource_for_each(resource, list)                                  \
++      for (resource = 0, resource = wl_resource_from_link((list)->next);      \
++           wl_resource_get_link(resource) != (list);                          \
++           resource = wl_resource_from_link(wl_resource_get_link(resource)->next))
++
++#define wl_resource_for_each_safe(resource, tmp, list)                                        \
++      for (resource = 0, tmp = 0,                                                     \
++           resource = wl_resource_from_link((list)->next),    \
++           tmp = wl_resource_from_link((list)->next->next);   \
++           wl_resource_get_link(resource) != (list);                          \
++           resource = tmp,                                                    \
++           tmp = wl_resource_from_link(wl_resource_get_link(resource)->next))
++
++struct wl_shm_buffer *
++wl_shm_buffer_get(struct wl_resource *resource);
++
++void
++wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer);
++
++void
++wl_shm_buffer_end_access(struct wl_shm_buffer *buffer);
++
++void *
++wl_shm_buffer_get_data(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer);
++
++uint32_t
++wl_shm_buffer_get_format(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_width(struct wl_shm_buffer *buffer);
++
++int32_t
++wl_shm_buffer_get_height(struct wl_shm_buffer *buffer);
++
++struct wl_shm_pool *
++wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer);
++
++void
++wl_shm_pool_unref(struct wl_shm_pool *pool);
++
++int
++wl_display_init_shm(struct wl_display *display);
++
++uint32_t *
++wl_display_add_shm_format(struct wl_display *display, uint32_t format);
++
++struct wl_shm_buffer *
++wl_shm_buffer_create(struct wl_client *client,
++                   uint32_t id, int32_t width, int32_t height,
++                   int32_t stride, uint32_t format) WL_DEPRECATED;
++
++void
++wl_log_set_handler_server(wl_log_func_t handler);
++
++enum wl_protocol_logger_type {
++      WL_PROTOCOL_LOGGER_REQUEST,
++      WL_PROTOCOL_LOGGER_EVENT,
++};
++
++struct wl_protocol_logger_message {
++      struct wl_resource *resource;
++      int message_opcode;
++      const struct wl_message *message;
++      int arguments_count;
++      const union wl_argument *arguments;
++};
++
++typedef void (*wl_protocol_logger_func_t)(void *user_data,
++                                        enum wl_protocol_logger_type direction,
++                                        const struct wl_protocol_logger_message *message);
++
++struct wl_protocol_logger *
++wl_display_add_protocol_logger(struct wl_display *display,
++                             wl_protocol_logger_func_t, void *user_data);
++
++void
++wl_protocol_logger_destroy(struct wl_protocol_logger *logger);
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..23fa4587689822d4c07dd95b75b1cf30f5e510a5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,53 @@@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_SERVER_PRIVATE_H
++#define WAYLAND_SERVER_PRIVATE_H
++
++#include "wayland-server-core.h"
++
++struct wl_priv_signal {
++      struct wl_list listener_list;
++      struct wl_list emit_list;
++};
++
++void
++wl_priv_signal_init(struct wl_priv_signal *signal);
++
++void
++wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener);
++
++struct wl_listener *
++wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify);
++
++void
++wl_priv_signal_emit(struct wl_priv_signal *signal, void *data);
++
++void
++wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data);
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a44982fbe9a3cde329f5eb2024202e5c5cf73e55
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2427 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++
++#include <stdbool.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stddef.h>
++#include <stdio.h>
++#include <stdarg.h>
++#include <errno.h>
++#include <string.h>
++#include <unistd.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <dlfcn.h>
++#include <assert.h>
++#include <sys/time.h>
++#include <fcntl.h>
++#include <sys/eventfd.h>
++#include <sys/file.h>
++#include <sys/stat.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server-private.h"
++#include "wayland-server.h"
++#include "wayland-os.h"
++
++/* This is the size of the char array in struct sock_addr_un.
++ * No Wayland socket can be created with a path longer than this,
++ * including the null terminator.
++ */
++#ifndef UNIX_PATH_MAX
++#define UNIX_PATH_MAX 108
++#endif
++
++#define LOCK_SUFFIX   ".lock"
++#define LOCK_SUFFIXLEN        5
++
++struct wl_socket {
++      int fd;
++      int fd_lock;
++      struct sockaddr_un addr;
++      char lock_addr[UNIX_PATH_MAX + LOCK_SUFFIXLEN];
++      struct wl_list link;
++      struct wl_event_source *source;
++      char *display_name;
++};
++
++struct wl_client {
++      struct wl_connection *connection;
++      struct wl_event_source *source;
++      struct wl_display *display;
++      struct wl_resource *display_resource;
++      struct wl_list link;
++      struct wl_map objects;
++      struct wl_priv_signal destroy_signal;
++      pid_t pid;
++      uid_t uid;
++      gid_t gid;
++      int error;
++      struct wl_priv_signal resource_created_signal;
++};
++
++struct wl_display {
++      struct wl_event_loop *loop;
++      int run;
++
++      uint32_t id;
++      uint32_t serial;
++
++      struct wl_list registry_resource_list;
++      struct wl_list global_list;
++      struct wl_list socket_list;
++      struct wl_list client_list;
++      struct wl_list protocol_loggers;
++
++      struct wl_priv_signal destroy_signal;
++      struct wl_priv_signal create_client_signal;
++
++      struct wl_array additional_shm_formats;
++
++      wl_display_global_filter_func_t global_filter;
++      void *global_filter_data;
++
++      int terminate_efd;
++      struct wl_event_source *term_source;
++};
++
++struct wl_global {
++      struct wl_display *display;
++      const struct wl_interface *interface;
++      uint32_t name;
++      uint32_t version;
++      void *data;
++      wl_global_bind_func_t bind;
++      struct wl_list link;
++      bool removed;
++};
++
++struct wl_resource {
++      struct wl_object object;
++      wl_resource_destroy_func_t destroy;
++      struct wl_list link;
++      /* Unfortunately some users of libwayland (e.g. mesa) still use the
++       * deprecated wl_resource struct, even if creating it with the new
++       * wl_resource_create(). So we cannot change the layout of the struct
++       * unless after the data field. */
++      struct wl_signal deprecated_destroy_signal;
++      struct wl_client *client;
++      void *data;
++      int version;
++      wl_dispatcher_func_t dispatcher;
++      struct wl_priv_signal destroy_signal;
++};
++
++struct wl_protocol_logger {
++      struct wl_list link;
++      wl_protocol_logger_func_t func;
++      void *user_data;
++};
++
++static int debug_server = 0;
++
++static void
++log_closure(struct wl_resource *resource,
++          struct wl_closure *closure, int send)
++{
++      struct wl_object *object = &resource->object;
++      struct wl_display *display = resource->client->display;
++      struct wl_protocol_logger *protocol_logger;
++      struct wl_protocol_logger_message message;
++
++      if (debug_server)
++              wl_closure_print(closure, object, send, false, NULL);
++
++      if (!wl_list_empty(&display->protocol_loggers)) {
++              message.resource = resource;
++              message.message_opcode = closure->opcode;
++              message.message = closure->message;
++              message.arguments_count = closure->count;
++              message.arguments = closure->args;
++              wl_list_for_each(protocol_logger,
++                               &display->protocol_loggers, link) {
++                      protocol_logger->func(protocol_logger->user_data,
++                                            send ? WL_PROTOCOL_LOGGER_EVENT :
++                                                   WL_PROTOCOL_LOGGER_REQUEST,
++                                            &message);
++              }
++      }
++}
++
++static bool
++verify_objects(struct wl_resource *resource, uint32_t opcode,
++             union wl_argument *args)
++{
++      struct wl_object *object = &resource->object;
++      const char *signature = object->interface->events[opcode].signature;
++      struct argument_details arg;
++      struct wl_resource *res;
++      int count, i;
++
++      count = arg_count_for_signature(signature);
++      for (i = 0; i < count; i++) {
++              signature = get_next_argument(signature, &arg);
++              switch (arg.type) {
++              case 'n':
++              case 'o':
++                      res = (struct wl_resource *) (args[i].o);
++                      if (res && res->client != resource->client) {
++                              wl_log("compositor bug: The compositor "
++                                     "tried to use an object from one "
++                                     "client in a '%s.%s' for a different "
++                                     "client.\n", object->interface->name,
++                                     object->interface->events[opcode].name);
++                              return false;
++                      }
++              }
++      }
++      return true;
++}
++
++static void
++handle_array(struct wl_resource *resource, uint32_t opcode,
++           union wl_argument *args,
++           int (*send_func)(struct wl_closure *, struct wl_connection *))
++{
++      struct wl_closure *closure;
++      struct wl_object *object = &resource->object;
++
++      if (resource->client->error)
++              return;
++
++      if (!verify_objects(resource, opcode, args)) {
++              resource->client->error = 1;
++              return;
++      }
++
++      closure = wl_closure_marshal(object, opcode, args,
++                                   &object->interface->events[opcode]);
++
++      if (closure == NULL) {
++              resource->client->error = 1;
++              return;
++      }
++
++      log_closure(resource, closure, true);
++
++      if (send_func(closure, resource->client->connection))
++              resource->client->error = 1;
++
++      wl_closure_destroy(closure);
++}
++
++WL_EXPORT void
++wl_resource_post_event_array(struct wl_resource *resource, uint32_t opcode,
++                           union wl_argument *args)
++{
++      handle_array(resource, opcode, args, wl_closure_send);
++}
++
++WL_EXPORT void
++wl_resource_post_event(struct wl_resource *resource, uint32_t opcode, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      struct wl_object *object = &resource->object;
++      va_list ap;
++
++      va_start(ap, opcode);
++      wl_argument_from_va_list(object->interface->events[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      wl_resource_post_event_array(resource, opcode, args);
++}
++
++
++WL_EXPORT void
++wl_resource_queue_event_array(struct wl_resource *resource, uint32_t opcode,
++                            union wl_argument *args)
++{
++      handle_array(resource, opcode, args, wl_closure_queue);
++}
++
++WL_EXPORT void
++wl_resource_queue_event(struct wl_resource *resource, uint32_t opcode, ...)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      struct wl_object *object = &resource->object;
++      va_list ap;
++
++      va_start(ap, opcode);
++      wl_argument_from_va_list(object->interface->events[opcode].signature,
++                               args, WL_CLOSURE_MAX_ARGS, ap);
++      va_end(ap);
++
++      wl_resource_queue_event_array(resource, opcode, args);
++}
++
++static void
++wl_resource_post_error_vargs(struct wl_resource *resource,
++                           uint32_t code, const char *msg, va_list argp)
++{
++      struct wl_client *client = resource->client;
++      char buffer[128];
++
++      vsnprintf(buffer, sizeof buffer, msg, argp);
++
++      /*
++       * When a client aborts, its resources are destroyed in id order,
++       * which means the display resource is destroyed first. If destruction
++       * of any later resources results in a protocol error, we end up here
++       * with a NULL display_resource. Do not try to send errors to an
++       * already dead client.
++       */
++      if (client->error || !client->display_resource)
++              return;
++
++      wl_resource_post_event(client->display_resource,
++                             WL_DISPLAY_ERROR, resource, code, buffer);
++      client->error = 1;
++
++}
++
++WL_EXPORT void
++wl_resource_post_error(struct wl_resource *resource,
++                     uint32_t code, const char *msg, ...)
++{
++      va_list ap;
++
++      va_start(ap, msg);
++      wl_resource_post_error_vargs(resource, code, msg, ap);
++      va_end(ap);
++}
++
++static void
++destroy_client_with_error(struct wl_client *client, const char *reason)
++{
++      wl_log("%s (pid %u)\n", reason, client->pid);
++      wl_client_destroy(client);
++}
++
++static int
++wl_client_connection_data(int fd, uint32_t mask, void *data)
++{
++      struct wl_client *client = data;
++      struct wl_connection *connection = client->connection;
++      struct wl_resource *resource;
++      struct wl_object *object;
++      struct wl_closure *closure;
++      const struct wl_message *message;
++      uint32_t p[2];
++      uint32_t resource_flags;
++      int opcode, size, since;
++      int len;
++
++      if (mask & WL_EVENT_HANGUP) {
++              wl_client_destroy(client);
++              return 1;
++      }
++
++      if (mask & WL_EVENT_ERROR) {
++              destroy_client_with_error(client, "socket error");
++              return 1;
++      }
++
++      if (mask & WL_EVENT_WRITABLE) {
++              len = wl_connection_flush(connection);
++              if (len < 0 && errno != EAGAIN) {
++                      destroy_client_with_error(
++                          client, "failed to flush client connection");
++                      return 1;
++              } else if (len >= 0) {
++                      wl_event_source_fd_update(client->source,
++                                                WL_EVENT_READABLE);
++              }
++      }
++
++      len = 0;
++      if (mask & WL_EVENT_READABLE) {
++              len = wl_connection_read(connection);
++              if (len == 0 || (len < 0 && errno != EAGAIN)) {
++                      destroy_client_with_error(
++                          client, "failed to read client connection");
++                      return 1;
++              }
++      }
++
++      while (len >= 0 && (size_t) len >= sizeof p) {
++              wl_connection_copy(connection, p, sizeof p);
++              opcode = p[1] & 0xffff;
++              size = p[1] >> 16;
++              if (len < size)
++                      break;
++
++              resource = wl_map_lookup(&client->objects, p[0]);
++              resource_flags = wl_map_lookup_flags(&client->objects, p[0]);
++              if (resource == NULL) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                             "invalid object %u", p[0]);
++                      break;
++              }
++
++              object = &resource->object;
++              if (opcode >= object->interface->method_count) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_METHOD,
++                                             "invalid method %d, object %s@%u",
++                                             opcode,
++                                             object->interface->name,
++                                             object->id);
++                      break;
++              }
++
++              message = &object->interface->methods[opcode];
++              since = wl_message_get_since(message);
++              if (!(resource_flags & WL_MAP_ENTRY_LEGACY) &&
++                  resource->version > 0 && resource->version < since) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_METHOD,
++                                             "invalid method %d (since %d < %d)"
++                                             ", object %s@%u",
++                                             opcode, resource->version, since,
++                                             object->interface->name,
++                                             object->id);
++                      break;
++              }
++
++
++              closure = wl_connection_demarshal(client->connection, size,
++                                                &client->objects, message);
++
++              if (closure == NULL && errno == ENOMEM) {
++                      wl_resource_post_no_memory(resource);
++                      break;
++              } else if (closure == NULL ||
++                         wl_closure_lookup_objects(closure, &client->objects) < 0) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_METHOD,
++                                             "invalid arguments for %s@%u.%s",
++                                             object->interface->name,
++                                             object->id,
++                                             message->name);
++                      wl_closure_destroy(closure);
++                      break;
++              }
++
++              log_closure(resource, closure, false);
++
++              if ((resource_flags & WL_MAP_ENTRY_LEGACY) ||
++                  resource->dispatcher == NULL) {
++                      wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER,
++                                        object, opcode, client);
++              } else {
++                      wl_closure_dispatch(closure, resource->dispatcher,
++                                          object, opcode);
++              }
++
++              wl_closure_destroy(closure);
++
++              if (client->error)
++                      break;
++
++              len = wl_connection_pending_input(connection);
++      }
++
++      if (client->error) {
++              destroy_client_with_error(client,
++                                        "error in client communication");
++      }
++
++      return 1;
++}
++
++/** Flush pending events to the client
++ *
++ * \param client The client object
++ *
++ * Events sent to clients are queued in a buffer and written to the
++ * socket later - typically when the compositor has handled all
++ * requests and goes back to block in the event loop.  This function
++ * flushes all queued up events for a client immediately.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_flush(struct wl_client *client)
++{
++      wl_connection_flush(client->connection);
++}
++
++/** Get the display object for the given client
++ *
++ * \param client The client object
++ * \return The display object the client is associated with.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_display *
++wl_client_get_display(struct wl_client *client)
++{
++      return client->display;
++}
++
++static int
++bind_display(struct wl_client *client, struct wl_display *display);
++
++/** Create a client for the given file descriptor
++ *
++ * \param display The display object
++ * \param fd The file descriptor for the socket to the client
++ * \return The new client object or NULL on failure.
++ *
++ * Given a file descriptor corresponding to one end of a socket, this
++ * function will create a wl_client struct and add the new client to
++ * the compositors client list.  At that point, the client is
++ * initialized and ready to run, as if the client had connected to the
++ * servers listening socket.  When the client eventually sends
++ * requests to the compositor, the wl_client argument to the request
++ * handler will be the wl_client returned from this function.
++ *
++ * The other end of the socket can be passed to
++ * wl_display_connect_to_fd() on the client side or used with the
++ * WAYLAND_SOCKET environment variable on the client side.
++ *
++ * Listeners added with wl_display_add_client_created_listener() will
++ * be notified by this function after the client is fully constructed.
++ *
++ * On failure this function sets errno accordingly and returns NULL.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_client *
++wl_client_create(struct wl_display *display, int fd)
++{
++      struct wl_client *client;
++
++      client = zalloc(sizeof *client);
++      if (client == NULL)
++              return NULL;
++
++      wl_priv_signal_init(&client->resource_created_signal);
++      client->display = display;
++      client->source = wl_event_loop_add_fd(display->loop, fd,
++                                            WL_EVENT_READABLE,
++                                            wl_client_connection_data, client);
++
++      if (!client->source)
++              goto err_client;
++
++      if (wl_os_socket_peercred(fd, &client->uid, &client->gid,
++                                &client->pid) != 0)
++              goto err_source;
++
++      client->connection = wl_connection_create(fd);
++      if (client->connection == NULL)
++              goto err_source;
++
++      wl_map_init(&client->objects, WL_MAP_SERVER_SIDE);
++
++      if (wl_map_insert_at(&client->objects, 0, 0, NULL) < 0)
++              goto err_map;
++
++      wl_priv_signal_init(&client->destroy_signal);
++      if (bind_display(client, display) < 0)
++              goto err_map;
++
++      wl_list_insert(display->client_list.prev, &client->link);
++
++      wl_priv_signal_emit(&display->create_client_signal, client);
++
++      return client;
++
++err_map:
++      wl_map_release(&client->objects);
++      wl_connection_destroy(client->connection);
++err_source:
++      wl_event_source_remove(client->source);
++err_client:
++      free(client);
++      return NULL;
++}
++
++/** Return Unix credentials for the client
++ *
++ * \param client The display object
++ * \param pid Returns the process ID
++ * \param uid Returns the user ID
++ * \param gid Returns the group ID
++ *
++ * This function returns the process ID, the user ID and the group ID
++ * for the given client.  The credentials come from getsockopt() with
++ * SO_PEERCRED, on the client socket fd.  All the pointers can be
++ * NULL, if the caller is not interested in a particular ID.
++ *
++ * Note, process IDs are subject to race conditions and are not a reliable way
++ * to identify a client.
++ *
++ * Be aware that for clients that a compositor forks and execs and
++ * then connects using socketpair(), this function will return the
++ * credentials for the compositor.  The credentials for the socketpair
++ * are set at creation time in the compositor.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_get_credentials(struct wl_client *client,
++                        pid_t *pid, uid_t *uid, gid_t *gid)
++{
++      if (pid)
++              *pid = client->pid;
++      if (uid)
++              *uid = client->uid;
++      if (gid)
++              *gid = client->gid;
++}
++
++/** Get the file descriptor for the client
++ *
++ * \param client The display object
++ * \return The file descriptor to use for the connection
++ *
++ * This function returns the file descriptor for the given client.
++ *
++ * Be sure to use the file descriptor from the client for inspection only.
++ * If the caller does anything to the file descriptor that changes its state,
++ * it will likely cause problems.
++ *
++ * See also wl_client_get_credentials().
++ * It is recommended that you evaluate whether wl_client_get_credentials()
++ * can be applied to your use case instead of this function.
++ *
++ * If you would like to distinguish just between the client and the compositor
++ * itself from the client's request, it can be done by getting the client
++ * credentials and by checking the PID of the client and the compositor's PID.
++ * Regarding the case in which the socketpair() is being used, you need to be
++ * careful. Please note the documentation for wl_client_get_credentials().
++ *
++ * This function can be used for a compositor to validate a request from
++ * a client if there are additional information provided from the client's
++ * file descriptor. For instance, suppose you can get the security contexts
++ * from the client's file descriptor. The compositor can validate the client's
++ * request with the contexts and make a decision whether it permits or deny it.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT int
++wl_client_get_fd(struct wl_client *client)
++{
++      return wl_connection_get_fd(client->connection);
++}
++
++/** Look up an object in the client name space
++ *
++ * \param client The client object
++ * \param id The object id
++ * \return The object or NULL if there is not object for the given ID
++ *
++ * This looks up an object in the client object name space by its
++ * object ID.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_resource *
++wl_client_get_object(struct wl_client *client, uint32_t id)
++{
++      return wl_map_lookup(&client->objects, id);
++}
++
++WL_EXPORT void
++wl_client_post_no_memory(struct wl_client *client)
++{
++      wl_resource_post_error(client->display_resource,
++                             WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
++}
++
++/** Report an internal server error
++ *
++ * \param client The client object
++ * \param msg A printf-style format string
++ * \param ... Format string arguments
++ *
++ * Report an unspecified internal implementation error and disconnect
++ * the client.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_post_implementation_error(struct wl_client *client,
++                                  char const *msg, ...)
++{
++      va_list ap;
++
++      va_start(ap, msg);
++      wl_resource_post_error_vargs(client->display_resource,
++                                   WL_DISPLAY_ERROR_IMPLEMENTATION,
++                                   msg, ap);
++      va_end(ap);
++}
++
++WL_EXPORT void
++wl_resource_post_no_memory(struct wl_resource *resource)
++{
++      wl_resource_post_error(resource->client->display_resource,
++                             WL_DISPLAY_ERROR_NO_MEMORY, "no memory");
++}
++
++/** Detect if a wl_resource uses the deprecated public definition.
++ *
++ * Before Wayland 1.2.0, the definition of struct wl_resource was public.
++ * It was made opaque just before 1.2.0, and later new fields were added.
++ * The new fields cannot be accessed if a program is using the deprecated
++ * definition, as there would not be memory allocated for them.
++ *
++ * The creation pattern for the deprecated definition was wl_resource_init()
++ * followed by wl_client_add_resource(). wl_resource_init() was an inline
++ * function and no longer exists, but binaries might still carry it.
++ * wl_client_add_resource() still exists for ABI compatibility.
++ */
++static bool
++resource_is_deprecated(struct wl_resource *resource)
++{
++      struct wl_map *map = &resource->client->objects;
++      int id = resource->object.id;
++
++      /* wl_client_add_resource() marks deprecated resources with the flag. */
++      if (wl_map_lookup_flags(map, id) & WL_MAP_ENTRY_LEGACY)
++              return true;
++
++      return false;
++}
++
++static enum wl_iterator_result
++destroy_resource(void *element, void *data, uint32_t flags)
++{
++      struct wl_resource *resource = element;
++
++      wl_signal_emit(&resource->deprecated_destroy_signal, resource);
++      /* Don't emit the new signal for deprecated resources, as that would
++       * access memory outside the bounds of the deprecated struct */
++      if (!resource_is_deprecated(resource))
++              wl_priv_signal_final_emit(&resource->destroy_signal, resource);
++
++      if (resource->destroy)
++              resource->destroy(resource);
++
++      if (!(flags & WL_MAP_ENTRY_LEGACY))
++              free(resource);
++
++      return WL_ITERATOR_CONTINUE;
++}
++
++WL_EXPORT void
++wl_resource_destroy(struct wl_resource *resource)
++{
++      struct wl_client *client = resource->client;
++      uint32_t id;
++      uint32_t flags;
++
++      id = resource->object.id;
++      flags = wl_map_lookup_flags(&client->objects, id);
++      destroy_resource(resource, NULL, flags);
++
++      if (id < WL_SERVER_ID_START) {
++              if (client->display_resource) {
++                      wl_resource_queue_event(client->display_resource,
++                                              WL_DISPLAY_DELETE_ID, id);
++              }
++              wl_map_insert_at(&client->objects, 0, id, NULL);
++      } else {
++              wl_map_remove(&client->objects, id);
++      }
++}
++
++WL_EXPORT uint32_t
++wl_resource_get_id(struct wl_resource *resource)
++{
++      return resource->object.id;
++}
++
++WL_EXPORT struct wl_list *
++wl_resource_get_link(struct wl_resource *resource)
++{
++      return &resource->link;
++}
++
++WL_EXPORT struct wl_resource *
++wl_resource_from_link(struct wl_list *link)
++{
++      struct wl_resource *resource;
++
++      return wl_container_of(link, resource, link);
++}
++
++WL_EXPORT struct wl_resource *
++wl_resource_find_for_client(struct wl_list *list, struct wl_client *client)
++{
++      struct wl_resource *resource;
++
++      if (client == NULL)
++              return NULL;
++
++      wl_list_for_each(resource, list, link) {
++              if (resource->client == client)
++                      return resource;
++      }
++
++      return NULL;
++}
++
++WL_EXPORT struct wl_client *
++wl_resource_get_client(struct wl_resource *resource)
++{
++      return resource->client;
++}
++
++WL_EXPORT void
++wl_resource_set_user_data(struct wl_resource *resource, void *data)
++{
++      resource->data = data;
++}
++
++WL_EXPORT void *
++wl_resource_get_user_data(struct wl_resource *resource)
++{
++      return resource->data;
++}
++
++WL_EXPORT int
++wl_resource_get_version(struct wl_resource *resource)
++{
++      return resource->version;
++}
++
++WL_EXPORT void
++wl_resource_set_destructor(struct wl_resource *resource,
++                         wl_resource_destroy_func_t destroy)
++{
++      resource->destroy = destroy;
++}
++
++WL_EXPORT int
++wl_resource_instance_of(struct wl_resource *resource,
++                      const struct wl_interface *interface,
++                      const void *implementation)
++{
++      return wl_interface_equal(resource->object.interface, interface) &&
++              resource->object.implementation == implementation;
++}
++
++WL_EXPORT void
++wl_resource_add_destroy_listener(struct wl_resource *resource,
++                               struct wl_listener * listener)
++{
++      if (resource_is_deprecated(resource))
++              wl_signal_add(&resource->deprecated_destroy_signal, listener);
++      else
++              wl_priv_signal_add(&resource->destroy_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_resource_get_destroy_listener(struct wl_resource *resource,
++                               wl_notify_func_t notify)
++{
++      if (resource_is_deprecated(resource))
++              return wl_signal_get(&resource->deprecated_destroy_signal, notify);
++      return wl_priv_signal_get(&resource->destroy_signal, notify);
++}
++
++/** Retrieve the interface name (class) of a resource object.
++ *
++ * \param resource The resource object
++ *
++ * \memberof wl_resource
++ */
++WL_EXPORT const char *
++wl_resource_get_class(struct wl_resource *resource)
++{
++      return resource->object.interface->name;
++}
++
++WL_EXPORT void
++wl_client_add_destroy_listener(struct wl_client *client,
++                             struct wl_listener *listener)
++{
++      wl_priv_signal_add(&client->destroy_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_client_get_destroy_listener(struct wl_client *client,
++                             wl_notify_func_t notify)
++{
++      return wl_priv_signal_get(&client->destroy_signal, notify);
++}
++
++WL_EXPORT void
++wl_client_destroy(struct wl_client *client)
++{
++      uint32_t serial = 0;
++
++      wl_priv_signal_final_emit(&client->destroy_signal, client);
++
++      wl_client_flush(client);
++      wl_map_for_each(&client->objects, destroy_resource, &serial);
++      wl_map_release(&client->objects);
++      wl_event_source_remove(client->source);
++      close(wl_connection_destroy(client->connection));
++      wl_list_remove(&client->link);
++      wl_list_remove(&client->resource_created_signal.listener_list);
++      free(client);
++}
++
++/* Check if a global filter is registered and use it if any.
++ *
++ * If no wl_global filter has been registered, this function will
++ * return true, allowing the wl_global to be visible to the wl_client
++ */
++static bool
++wl_global_is_visible(const struct wl_client *client,
++            const struct wl_global *global)
++{
++      struct wl_display *display = client->display;
++
++      return (display->global_filter == NULL ||
++              display->global_filter(client, global, display->global_filter_data));
++}
++
++static void
++registry_bind(struct wl_client *client,
++            struct wl_resource *resource, uint32_t name,
++            const char *interface, uint32_t version, uint32_t id)
++{
++      struct wl_global *global;
++      struct wl_display *display = resource->data;
++
++      wl_list_for_each(global, &display->global_list, link)
++              if (global->name == name)
++                      break;
++
++      if (&global->link == &display->global_list)
++              wl_resource_post_error(resource,
++                                     WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                     "invalid global %s (%d)", interface, name);
++      else if (strcmp(global->interface->name, interface) != 0)
++              wl_resource_post_error(resource,
++                                     WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                     "invalid interface for global %u: "
++                                     "have %s, wanted %s",
++                                     name, interface, global->interface->name);
++      else if (version == 0)
++              wl_resource_post_error(resource,
++                                     WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                     "invalid version for global %s (%d): 0 is not a valid version",
++                                     interface, name);
++      else if (global->version < version)
++              wl_resource_post_error(resource,
++                                     WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                     "invalid version for global %s (%d): have %d, wanted %d",
++                                     interface, name, global->version, version);
++      else if (!wl_global_is_visible(client, global))
++              wl_resource_post_error(resource,
++                                     WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                     "invalid global %s (%d)", interface, name);
++      else
++              global->bind(client, global->data, version, id);
++}
++
++static const struct wl_registry_interface registry_interface = {
++      registry_bind
++};
++
++static void
++display_sync(struct wl_client *client,
++           struct wl_resource *resource, uint32_t id)
++{
++      struct wl_resource *callback;
++      uint32_t serial;
++
++      callback = wl_resource_create(client, &wl_callback_interface, 1, id);
++      if (callback == NULL) {
++              wl_client_post_no_memory(client);
++              return;
++      }
++
++      serial = wl_display_get_serial(client->display);
++      wl_callback_send_done(callback, serial);
++      wl_resource_destroy(callback);
++}
++
++static void
++unbind_resource(struct wl_resource *resource)
++{
++      wl_list_remove(&resource->link);
++}
++
++static void
++display_get_registry(struct wl_client *client,
++                   struct wl_resource *resource, uint32_t id)
++{
++      struct wl_display *display = resource->data;
++      struct wl_resource *registry_resource;
++      struct wl_global *global;
++
++      registry_resource =
++              wl_resource_create(client, &wl_registry_interface, 1, id);
++      if (registry_resource == NULL) {
++              wl_client_post_no_memory(client);
++              return;
++      }
++
++      wl_resource_set_implementation(registry_resource,
++                                     &registry_interface,
++                                     display, unbind_resource);
++
++      wl_list_insert(&display->registry_resource_list,
++                     &registry_resource->link);
++
++      wl_list_for_each(global, &display->global_list, link)
++              if (wl_global_is_visible(client, global) && !global->removed)
++                      wl_resource_post_event(registry_resource,
++                                             WL_REGISTRY_GLOBAL,
++                                             global->name,
++                                             global->interface->name,
++                                             global->version);
++}
++
++static const struct wl_display_interface display_interface = {
++      display_sync,
++      display_get_registry
++};
++
++static void
++destroy_client_display_resource(struct wl_resource *resource)
++{
++      resource->client->display_resource = NULL;
++}
++
++static int
++bind_display(struct wl_client *client, struct wl_display *display)
++{
++      client->display_resource =
++              wl_resource_create(client, &wl_display_interface, 1, 1);
++      if (client->display_resource == NULL) {
++              /* DON'T send no-memory error to client - it has no
++               * resource to which it could post the event */
++              return -1;
++      }
++
++      wl_resource_set_implementation(client->display_resource,
++                                     &display_interface, display,
++                                     destroy_client_display_resource);
++      return 0;
++}
++
++static int
++handle_display_terminate(int fd, uint32_t mask, void *data) {
++      uint64_t term_event;
++
++      if (read(fd, &term_event, sizeof(term_event)) < 0 && errno != EAGAIN)
++              return -1;
++
++      return 0;
++}
++
++/** Create Wayland display object.
++ *
++ * \return The Wayland display object. Null if failed to create
++ *
++ * This creates the wl_display object.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_display *
++wl_display_create(void)
++{
++      struct wl_display *display;
++      const char *debug;
++
++      debug = getenv("WAYLAND_DEBUG");
++      if (debug && (strstr(debug, "server") || strstr(debug, "1")))
++              debug_server = 1;
++
++      display = zalloc(sizeof *display);
++      if (display == NULL)
++              return NULL;
++
++      display->loop = wl_event_loop_create();
++      if (display->loop == NULL) {
++              free(display);
++              return NULL;
++      }
++
++      display->terminate_efd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
++      if (display->terminate_efd < 0)
++              goto err_eventfd;
++
++      display->term_source = wl_event_loop_add_fd(display->loop,
++                                                  display->terminate_efd,
++                                                  WL_EVENT_READABLE,
++                                                  handle_display_terminate,
++                                                  NULL);
++
++      if (display->term_source == NULL)
++              goto err_term_source;
++
++      wl_list_init(&display->global_list);
++      wl_list_init(&display->socket_list);
++      wl_list_init(&display->client_list);
++      wl_list_init(&display->registry_resource_list);
++      wl_list_init(&display->protocol_loggers);
++
++      wl_priv_signal_init(&display->destroy_signal);
++      wl_priv_signal_init(&display->create_client_signal);
++
++      display->id = 1;
++      display->serial = 0;
++
++      display->global_filter = NULL;
++      display->global_filter_data = NULL;
++
++      wl_array_init(&display->additional_shm_formats);
++
++      return display;
++
++err_term_source:
++      close(display->terminate_efd);
++err_eventfd:
++      wl_event_loop_destroy(display->loop);
++      free(display);
++      return NULL;
++}
++
++static void
++wl_socket_destroy(struct wl_socket *s)
++{
++      if (s->source)
++              wl_event_source_remove(s->source);
++      if (s->addr.sun_path[0])
++              unlink(s->addr.sun_path);
++      if (s->fd >= 0)
++              close(s->fd);
++      if (s->lock_addr[0])
++              unlink(s->lock_addr);
++      if (s->fd_lock >= 0)
++              close(s->fd_lock);
++
++      free(s);
++}
++
++static struct wl_socket *
++wl_socket_alloc(void)
++{
++      struct wl_socket *s;
++
++      s = zalloc(sizeof *s);
++      if (!s)
++              return NULL;
++
++      s->fd = -1;
++      s->fd_lock = -1;
++
++      return s;
++}
++
++/** Destroy Wayland display object.
++ *
++ * \param display The Wayland display object which should be destroyed.
++ * \return None.
++ *
++ * This function emits the wl_display destroy signal, releases
++ * all the sockets added to this display, free's all the globals associated
++ * with this display, free's memory of additional shared memory formats and
++ * destroy the display object.
++ *
++ * \sa wl_display_add_destroy_listener
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_destroy(struct wl_display *display)
++{
++      struct wl_socket *s, *next;
++      struct wl_global *global, *gnext;
++
++      wl_priv_signal_final_emit(&display->destroy_signal, display);
++
++      wl_list_for_each_safe(s, next, &display->socket_list, link) {
++              wl_socket_destroy(s);
++      }
++
++      close(display->terminate_efd);
++      wl_event_source_remove(display->term_source);
++
++      wl_event_loop_destroy(display->loop);
++
++      wl_list_for_each_safe(global, gnext, &display->global_list, link)
++              free(global);
++
++      wl_array_release(&display->additional_shm_formats);
++
++      wl_list_remove(&display->protocol_loggers);
++
++      free(display);
++}
++
++/** Set a filter function for global objects
++ *
++ * \param display The Wayland display object.
++ * \param filter  The global filter function.
++ * \param data User data to be associated with the global filter.
++ * \return None.
++ *
++ * Set a filter for the wl_display to advertise or hide global objects
++ * to clients.
++ * The set filter will be used during wl_global advertisement to
++ * determine whether a global object should be advertised to a
++ * given client, and during wl_global binding to determine whether
++ * a given client should be allowed to bind to a global.
++ *
++ * Clients that try to bind to a global that was filtered out will
++ * have an error raised.
++ *
++ * Setting the filter NULL will result in all globals being
++ * advertised to all clients. The default is no filter.
++ *
++ * The filter should be installed before any client connects and should always
++ * take the same decision given a client and a global. Not doing so will result
++ * in inconsistent filtering and broken wl_registry event sequences.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_set_global_filter(struct wl_display *display,
++                           wl_display_global_filter_func_t filter,
++                           void *data)
++{
++      display->global_filter = filter;
++      display->global_filter_data = data;
++}
++
++WL_EXPORT struct wl_global *
++wl_global_create(struct wl_display *display,
++               const struct wl_interface *interface, int version,
++               void *data, wl_global_bind_func_t bind)
++{
++      struct wl_global *global;
++      struct wl_resource *resource;
++
++      if (version < 1) {
++              wl_log("wl_global_create: failing to create interface "
++                     "'%s' with version %d because it is less than 1\n",
++                      interface->name, version);
++              return NULL;
++      }
++
++      if (version > interface->version) {
++              wl_log("wl_global_create: implemented version for '%s' "
++                     "higher than interface version (%d > %d)\n",
++                     interface->name, version, interface->version);
++              return NULL;
++      }
++
++      global = zalloc(sizeof *global);
++      if (global == NULL)
++              return NULL;
++
++      global->display = display;
++      global->name = display->id++;
++      global->interface = interface;
++      global->version = version;
++      global->data = data;
++      global->bind = bind;
++      global->removed = false;
++      wl_list_insert(display->global_list.prev, &global->link);
++
++      wl_list_for_each(resource, &display->registry_resource_list, link)
++              if (wl_global_is_visible(resource->client, global))
++                      wl_resource_post_event(resource,
++                                             WL_REGISTRY_GLOBAL,
++                                             global->name,
++                                             global->interface->name,
++                                             global->version);
++
++      return global;
++}
++
++/** Remove the global
++ *
++ * \param global The Wayland global.
++ *
++ * Broadcast a global remove event to all clients without destroying the
++ * global. This function can only be called once per global.
++ *
++ * wl_global_destroy() removes the global and immediately destroys it. On
++ * the other end, this function only removes the global, allowing clients
++ * that have not yet received the global remove event to continue to bind to
++ * it.
++ *
++ * This can be used by compositors to mitigate clients being disconnected
++ * because a global has been added and removed too quickly. Compositors can call
++ * wl_global_remove(), then wait an implementation-defined amount of time, then
++ * call wl_global_destroy(). Note that the destruction of a global is still
++ * racy, since clients have no way to acknowledge that they received the remove
++ * event.
++ *
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_global_remove(struct wl_global *global)
++{
++      struct wl_display *display = global->display;
++      struct wl_resource *resource;
++
++      if (global->removed)
++              wl_abort("wl_global_remove: called twice on the same "
++                       "global '%s@%"PRIu32"'", global->interface->name,
++                       global->name);
++
++      wl_list_for_each(resource, &display->registry_resource_list, link)
++              if (wl_global_is_visible(resource->client, global))
++                      wl_resource_post_event(resource, WL_REGISTRY_GLOBAL_REMOVE,
++                                             global->name);
++
++      global->removed = true;
++}
++
++WL_EXPORT void
++wl_global_destroy(struct wl_global *global)
++{
++      if (!global->removed)
++              wl_global_remove(global);
++      wl_list_remove(&global->link);
++      free(global);
++}
++
++WL_EXPORT const struct wl_interface *
++wl_global_get_interface(const struct wl_global *global)
++{
++      return global->interface;
++}
++
++/** Get the version of the given global.
++ *
++ * \param global The global object.
++ * \return The version advertised by the global.
++ *
++ * \memberof wl_global
++ * \since 1.21
++ */
++WL_EXPORT uint32_t
++wl_global_get_version(const struct wl_global *global)
++{
++      return global->version;
++}
++
++/** Get the display object for the given global
++ *
++ * \param global The global object
++ * \return The display object the global is associated with.
++ *
++ * \memberof wl_global
++ * \since 1.20
++ */
++WL_EXPORT struct wl_display *
++wl_global_get_display(const struct wl_global *global)
++{
++      return global->display;
++}
++
++WL_EXPORT void *
++wl_global_get_user_data(const struct wl_global *global)
++{
++      return global->data;
++}
++
++/** Set the global's user data
++ *
++ * \param global The global object
++ * \param data The user data pointer
++ *
++ * \since 1.17.90
++ */
++WL_EXPORT void
++wl_global_set_user_data(struct wl_global *global, void *data)
++{
++      global->data = data;
++}
++
++/** Get the current serial number
++ *
++ * \param display The display object
++ *
++ * This function returns the most recent serial number, but does not
++ * increment it.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_get_serial(struct wl_display *display)
++{
++      return display->serial;
++}
++
++/** Get the next serial number
++ *
++ * \param display The display object
++ *
++ * This function increments the display serial number and returns the
++ * new value.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t
++wl_display_next_serial(struct wl_display *display)
++{
++      display->serial++;
++
++      return display->serial;
++}
++
++WL_EXPORT struct wl_event_loop *
++wl_display_get_event_loop(struct wl_display *display)
++{
++      return display->loop;
++}
++
++WL_EXPORT void
++wl_display_terminate(struct wl_display *display)
++{
++      int ret;
++      uint64_t terminate = 1;
++
++      display->run = 0;
++
++      ret = write(display->terminate_efd, &terminate, sizeof(terminate));
++      assert (ret >= 0 || errno == EAGAIN);
++}
++
++WL_EXPORT void
++wl_display_run(struct wl_display *display)
++{
++      display->run = 1;
++
++      while (display->run) {
++              wl_display_flush_clients(display);
++              wl_event_loop_dispatch(display->loop, -1);
++      }
++}
++
++WL_EXPORT void
++wl_display_flush_clients(struct wl_display *display)
++{
++      struct wl_client *client, *next;
++      int ret;
++
++      wl_list_for_each_safe(client, next, &display->client_list, link) {
++              ret = wl_connection_flush(client->connection);
++              if (ret < 0 && errno == EAGAIN) {
++                      wl_event_source_fd_update(client->source,
++                                                WL_EVENT_WRITABLE |
++                                                WL_EVENT_READABLE);
++              } else if (ret < 0) {
++                      wl_client_destroy(client);
++              }
++      }
++}
++
++/** Destroy all clients connected to the display
++ *
++ * \param display The display object
++ *
++ * This function should be called right before wl_display_destroy() to ensure
++ * all client resources are closed properly. Destroying a client from within
++ * wl_display_destroy_clients() is safe, but creating one will leak resources
++ * and raise a warning.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT void
++wl_display_destroy_clients(struct wl_display *display)
++{
++      struct wl_list tmp_client_list, *pos;
++      struct wl_client *client;
++
++      /* Move the whole client list to a temporary head because some new clients
++       * might be added to the original head. */
++      wl_list_init(&tmp_client_list);
++      wl_list_insert_list(&tmp_client_list, &display->client_list);
++      wl_list_init(&display->client_list);
++
++      /* wl_list_for_each_safe isn't enough here: it fails if the next client is
++       * destroyed by the destroy handler of the current one. */
++      while (!wl_list_empty(&tmp_client_list)) {
++              pos = tmp_client_list.next;
++              client = wl_container_of(pos, client, link);
++
++              wl_client_destroy(client);
++      }
++
++      if (!wl_list_empty(&display->client_list)) {
++              wl_log("wl_display_destroy_clients: cannot destroy all clients because "
++                         "new ones were created by destroy callbacks\n");
++      }
++}
++
++static int
++socket_data(int fd, uint32_t mask, void *data)
++{
++      struct wl_display *display = data;
++      struct sockaddr_un name;
++      socklen_t length;
++      int client_fd;
++
++      length = sizeof name;
++      client_fd = wl_os_accept_cloexec(fd, (struct sockaddr *) &name,
++                                       &length);
++      if (client_fd < 0)
++              wl_log("failed to accept: %s\n", strerror(errno));
++      else
++              if (!wl_client_create(display, client_fd))
++                      close(client_fd);
++
++      return 1;
++}
++
++static int
++wl_socket_lock(struct wl_socket *socket)
++{
++      struct stat socket_stat;
++
++      snprintf(socket->lock_addr, sizeof socket->lock_addr,
++               "%s%s", socket->addr.sun_path, LOCK_SUFFIX);
++
++      socket->fd_lock = open(socket->lock_addr, O_CREAT | O_CLOEXEC | O_RDWR,
++                             (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));
++
++      if (socket->fd_lock < 0) {
++              wl_log("unable to open lockfile %s check permissions\n",
++                      socket->lock_addr);
++              goto err;
++      }
++
++      if (flock(socket->fd_lock, LOCK_EX | LOCK_NB) < 0) {
++              wl_log("unable to lock lockfile %s, maybe another compositor is running\n",
++                      socket->lock_addr);
++              goto err_fd;
++      }
++
++      if (lstat(socket->addr.sun_path, &socket_stat) < 0 ) {
++              if (errno != ENOENT) {
++                      wl_log("did not manage to stat file %s\n",
++                              socket->addr.sun_path);
++                      goto err_fd;
++              }
++      } else if (socket_stat.st_mode & S_IWUSR ||
++                 socket_stat.st_mode & S_IWGRP) {
++              unlink(socket->addr.sun_path);
++      }
++
++      return 0;
++err_fd:
++      close(socket->fd_lock);
++      socket->fd_lock = -1;
++err:
++      *socket->lock_addr = 0;
++      /* we did not set this value here, but without lock the
++       * socket won't be created anyway. This prevents the
++       * wl_socket_destroy from unlinking already existing socket
++       * created by other compositor */
++      *socket->addr.sun_path = 0;
++
++      return -1;
++}
++
++static int
++wl_socket_init_for_display_name(struct wl_socket *s, const char *name)
++{
++      int name_size;
++      const char *runtime_dir = "";
++      const char *separator = "";
++
++      if (name[0] != '/') {
++              runtime_dir = getenv("XDG_RUNTIME_DIR");
++              if (!runtime_dir || runtime_dir[0] != '/') {
++                      wl_log("error: XDG_RUNTIME_DIR is invalid or not set in"
++                             " the environment\n");
++
++                      /* to prevent programs reporting
++                       * "failed to add socket: Success" */
++                      errno = ENOENT;
++                      return -1;
++              }
++              separator = "/";
++      }
++
++      s->addr.sun_family = AF_LOCAL;
++      name_size = snprintf(s->addr.sun_path, sizeof s->addr.sun_path,
++                           "%s%s%s", runtime_dir, separator, name) + 1;
++
++      assert(name_size > 0);
++      if (name_size > (int)sizeof s->addr.sun_path) {
++              wl_log("error: socket path \"%s%s%s\" plus null terminator"
++                     " exceeds 108 bytes\n", runtime_dir, separator, name);
++              *s->addr.sun_path = 0;
++              /* to prevent programs reporting
++               * "failed to add socket: Success" */
++              errno = ENAMETOOLONG;
++              return -1;
++      }
++
++      s->display_name = (s->addr.sun_path + name_size - 1) - strlen(name);
++
++      return 0;
++}
++
++static int
++_wl_display_add_socket(struct wl_display *display, struct wl_socket *s)
++{
++      socklen_t size;
++
++      s->fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++      if (s->fd < 0) {
++              return -1;
++      }
++
++      size = offsetof (struct sockaddr_un, sun_path) + strlen(s->addr.sun_path);
++      if (bind(s->fd, (struct sockaddr *) &s->addr, size) < 0) {
++              wl_log("bind() failed with error: %s\n", strerror(errno));
++              return -1;
++      }
++
++      if (listen(s->fd, 128) < 0) {
++              wl_log("listen() failed with error: %s\n", strerror(errno));
++              return -1;
++      }
++
++      s->source = wl_event_loop_add_fd(display->loop, s->fd,
++                                       WL_EVENT_READABLE,
++                                       socket_data, display);
++      if (s->source == NULL) {
++              return -1;
++      }
++
++      wl_list_insert(display->socket_list.prev, &s->link);
++      return 0;
++}
++
++WL_EXPORT const char *
++wl_display_add_socket_auto(struct wl_display *display)
++{
++      struct wl_socket *s;
++      int displayno = 0;
++      char display_name[20] = "";
++
++      /* A reasonable number of maximum default sockets. If
++       * you need more than this, use the explicit add_socket API. */
++      const int MAX_DISPLAYNO = 32;
++
++      s = wl_socket_alloc();
++      if (s == NULL)
++              return NULL;
++
++      do {
++              snprintf(display_name, sizeof display_name, "wayland-%d", displayno);
++              if (wl_socket_init_for_display_name(s, display_name) < 0) {
++                      wl_socket_destroy(s);
++                      return NULL;
++              }
++
++              if (wl_socket_lock(s) < 0)
++                      continue;
++
++              if (_wl_display_add_socket(display, s) < 0) {
++                      wl_socket_destroy(s);
++                      return NULL;
++              }
++
++              return s->display_name;
++      } while (displayno++ < MAX_DISPLAYNO);
++
++      /* Ran out of display names. */
++      wl_socket_destroy(s);
++      errno = EINVAL;
++      return NULL;
++}
++
++/**  Add a socket with an existing fd to Wayland display for the clients to connect.
++ *
++ * \param display Wayland display to which the socket should be added.
++ * \param sock_fd The existing socket file descriptor to be used
++ * \return 0 if success. -1 if failed.
++ *
++ * The existing socket fd must already be created, opened, and locked.
++ * The fd must be properly set to CLOEXEC and bound to a socket file
++ * with both bind() and listen() already called.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_add_socket_fd(struct wl_display *display, int sock_fd)
++{
++      struct wl_socket *s;
++      struct stat buf;
++
++      /* Require a valid fd or fail */
++      if (sock_fd < 0 || fstat(sock_fd, &buf) < 0 || !S_ISSOCK(buf.st_mode)) {
++              return -1;
++      }
++
++      s = wl_socket_alloc();
++      if (s == NULL)
++              return -1;
++
++      s->source = wl_event_loop_add_fd(display->loop, sock_fd,
++                                       WL_EVENT_READABLE,
++                                       socket_data, display);
++      if (s->source == NULL) {
++              wl_log("failed to establish event source\n");
++              wl_socket_destroy(s);
++              return -1;
++      }
++
++      /* Reuse the existing fd */
++      s->fd = sock_fd;
++
++      wl_list_insert(display->socket_list.prev, &s->link);
++
++      return 0;
++}
++
++/** Add a socket to Wayland display for the clients to connect.
++ *
++ * \param display Wayland display to which the socket should be added.
++ * \param name Name of the Unix socket.
++ * \return 0 if success. -1 if failed.
++ *
++ * This adds a Unix socket to Wayland display which can be used by clients to
++ * connect to Wayland display.
++ *
++ * If NULL is passed as name, then it would look for WAYLAND_DISPLAY env
++ * variable for the socket name. If WAYLAND_DISPLAY is not set, then default
++ * wayland-0 is used.
++ *
++ * If the socket name is a relative path, the Unix socket will be created in
++ * the directory pointed to by environment variable XDG_RUNTIME_DIR. If
++ * XDG_RUNTIME_DIR is invalid or not set, then this function fails and returns -1.
++ *
++ * If the socket name is an absolute path, then it is used as-is for the
++ * the Unix socket.
++ *
++ * The length of the computed socket path must not exceed the maximum length
++ * of a Unix socket path.
++ * The function also fails if the user does not have write permission in the
++ * directory or if the path is already in use.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT int
++wl_display_add_socket(struct wl_display *display, const char *name)
++{
++      struct wl_socket *s;
++
++      s = wl_socket_alloc();
++      if (s == NULL)
++              return -1;
++
++      if (name == NULL)
++              name = getenv("WAYLAND_DISPLAY");
++      if (name == NULL)
++              name = "wayland-0";
++
++      if (wl_socket_init_for_display_name(s, name) < 0) {
++              wl_socket_destroy(s);
++              return -1;
++      }
++
++      if (wl_socket_lock(s) < 0) {
++              wl_socket_destroy(s);
++              return -1;
++      }
++
++      if (_wl_display_add_socket(display, s) < 0) {
++              wl_socket_destroy(s);
++              return -1;
++      }
++
++      return 0;
++}
++
++WL_EXPORT void
++wl_display_add_destroy_listener(struct wl_display *display,
++                              struct wl_listener *listener)
++{
++      wl_priv_signal_add(&display->destroy_signal, listener);
++}
++
++/** Registers a listener for the client connection signal.
++ *  When a new client object is created, \a listener will be notified, carrying
++ *  a pointer to the new wl_client object.
++ *
++ *  \ref wl_client_create
++ *  \ref wl_display
++ *  \ref wl_listener
++ *
++ * \param display The display object
++ * \param listener Signal handler object
++ */
++WL_EXPORT void
++wl_display_add_client_created_listener(struct wl_display *display,
++                                      struct wl_listener *listener)
++{
++      wl_priv_signal_add(&display->create_client_signal, listener);
++}
++
++WL_EXPORT struct wl_listener *
++wl_display_get_destroy_listener(struct wl_display *display,
++                              wl_notify_func_t notify)
++{
++      return wl_priv_signal_get(&display->destroy_signal, notify);
++}
++
++WL_EXPORT void
++wl_resource_set_implementation(struct wl_resource *resource,
++                             const void *implementation,
++                             void *data, wl_resource_destroy_func_t destroy)
++{
++      resource->object.implementation = implementation;
++      resource->data = data;
++      resource->destroy = destroy;
++      resource->dispatcher = NULL;
++}
++
++WL_EXPORT void
++wl_resource_set_dispatcher(struct wl_resource *resource,
++                         wl_dispatcher_func_t dispatcher,
++                         const void *implementation,
++                         void *data, wl_resource_destroy_func_t destroy)
++{
++      resource->dispatcher = dispatcher;
++      resource->object.implementation = implementation;
++      resource->data = data;
++      resource->destroy = destroy;
++}
++
++/** Create a new resource object
++ *
++ * \param client The client owner of the new resource.
++ * \param interface The interface of the new resource.
++ * \param version The version of the new resource.
++ * \param id The id of the new resource. If 0, an available id will be used.
++ *
++ * Listeners added with \a wl_client_add_resource_created_listener will be
++ * notified at the end of this function.
++ *
++ * \memberof wl_resource
++ */
++WL_EXPORT struct wl_resource *
++wl_resource_create(struct wl_client *client,
++                 const struct wl_interface *interface,
++                 int version, uint32_t id)
++{
++      struct wl_resource *resource;
++
++      resource = zalloc(sizeof *resource);
++      if (resource == NULL)
++              return NULL;
++
++      if (id == 0) {
++              id = wl_map_insert_new(&client->objects, 0, NULL);
++              if (id == 0) {
++                      free(resource);
++                      return NULL;
++              }
++      }
++
++      resource->object.id = id;
++      resource->object.interface = interface;
++      resource->object.implementation = NULL;
++
++      wl_signal_init(&resource->deprecated_destroy_signal);
++      wl_priv_signal_init(&resource->destroy_signal);
++
++      resource->destroy = NULL;
++      resource->client = client;
++      resource->data = NULL;
++      resource->version = version;
++      resource->dispatcher = NULL;
++
++      if (wl_map_insert_at(&client->objects, 0, id, resource) < 0) {
++              if (errno == EINVAL) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                             "invalid new id %d", id);
++              }
++              free(resource);
++              return NULL;
++      }
++
++      wl_priv_signal_emit(&client->resource_created_signal, resource);
++      return resource;
++}
++
++WL_EXPORT void
++wl_log_set_handler_server(wl_log_func_t handler)
++{
++      wl_log_handler = handler;
++}
++
++/** Adds a new protocol logger.
++ *
++ * When a new protocol message arrives or is sent from the server
++ * all the protocol logger functions will be called, carrying the
++ * \a user_data pointer, the type of the message (request or
++ * event) and the actual message.
++ * The lifetime of the messages passed to the logger function ends
++ * when they return so the messages cannot be stored and accessed
++ * later.
++ *
++ * \a errno is set on error.
++ *
++ * \param display The display object
++ * \param func The function to call to log a new protocol message
++ * \param user_data The user data pointer to pass to \a func
++ *
++ * \return The protol logger object on success, NULL on failure.
++ *
++ * \sa wl_protocol_logger_destroy
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_protocol_logger *
++wl_display_add_protocol_logger(struct wl_display *display,
++                             wl_protocol_logger_func_t func, void *user_data)
++{
++      struct wl_protocol_logger *logger;
++
++      logger = zalloc(sizeof *logger);
++      if (!logger)
++              return NULL;
++
++      logger->func = func;
++      logger->user_data = user_data;
++      wl_list_insert(&display->protocol_loggers, &logger->link);
++
++      return logger;
++}
++
++/** Destroys a protocol logger.
++ *
++ * This function destroys a protocol logger and removes it from the display
++ * it was added to with \a wl_display_add_protocol_logger.
++ * The \a logger object becomes invalid after calling this function.
++ *
++ * \sa wl_display_add_protocol_logger
++ *
++ * \memberof wl_protocol_logger
++ */
++WL_EXPORT void
++wl_protocol_logger_destroy(struct wl_protocol_logger *logger)
++{
++      wl_list_remove(&logger->link);
++      free(logger);
++}
++
++/** Add support for a wl_shm pixel format
++ *
++ * \param display The display object
++ * \param format The wl_shm pixel format to advertise
++ * \return A pointer to the wl_shm format that was added to the list
++ * or NULL if adding it to the list failed.
++ *
++ * Add the specified wl_shm format to the list of formats the wl_shm
++ * object advertises when a client binds to it.  Adding a format to
++ * the list means that clients will know that the compositor supports
++ * this format and may use it for creating wl_shm buffers.  The
++ * compositor must be able to handle the pixel format when a client
++ * requests it.
++ *
++ * The compositor by default supports WL_SHM_FORMAT_ARGB8888 and
++ * WL_SHM_FORMAT_XRGB8888.
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT uint32_t *
++wl_display_add_shm_format(struct wl_display *display, uint32_t format)
++{
++      uint32_t *p = NULL;
++
++      p = wl_array_add(&display->additional_shm_formats, sizeof *p);
++
++      if (p != NULL)
++              *p = format;
++      return p;
++}
++
++/**
++ * Get list of additional wl_shm pixel formats
++ *
++ * \param display The display object
++ *
++ * This function returns the list of addition wl_shm pixel formats
++ * that the compositor supports.  WL_SHM_FORMAT_ARGB8888 and
++ * WL_SHM_FORMAT_XRGB8888 are always supported and not included in the
++ * array, but all formats added through wl_display_add_shm_format()
++ * will be in the array.
++ *
++ * \sa wl_display_add_shm_format()
++ *
++ * \private
++ *
++ * \memberof wl_display
++ */
++struct wl_array *
++wl_display_get_additional_shm_formats(struct wl_display *display)
++{
++      return &display->additional_shm_formats;
++}
++
++/** Get the list of currently connected clients
++ *
++ * \param display The display object
++ *
++ * This function returns a pointer to the list of clients currently
++ * connected to the display. You can iterate on the list by using
++ * the \a wl_client_for_each macro.
++ * The returned value is valid for the lifetime of the \a display.
++ * You must not modify the returned list, but only access it.
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_client_get_link()
++ * \sa wl_client_from_link()
++ *
++ * \memberof wl_display
++ */
++WL_EXPORT struct wl_list *
++wl_display_get_client_list(struct wl_display *display)
++{
++      return &display->client_list;
++}
++
++/** Get the link by which a client is inserted in the client list
++ *
++ * \param client The client object
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_display_get_client_list()
++ * \sa wl_client_from_link()
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_list *
++wl_client_get_link(struct wl_client *client)
++{
++      return &client->link;
++}
++
++/** Get a wl_client by its link
++ *
++ * \param link The link of a wl_client
++ *
++ * \sa wl_client_for_each()
++ * \sa wl_display_get_client_list()
++ * \sa wl_client_get_link()
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT struct wl_client *
++wl_client_from_link(struct wl_list *link)
++{
++      struct wl_client *client;
++
++      return wl_container_of(link, client, link);
++}
++
++/** Add a listener for the client's resource creation signal
++ *
++ * \param client The client object
++ * \param listener The listener to be added
++ *
++ * When a new resource is created for this client the listener
++ * will be notified, carrying the new resource as the data argument.
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_add_resource_created_listener(struct wl_client *client,
++                                      struct wl_listener *listener)
++{
++      wl_priv_signal_add(&client->resource_created_signal, listener);
++}
++
++struct wl_resource_iterator_context {
++      void *user_data;
++      wl_client_for_each_resource_iterator_func_t it;
++};
++
++static enum wl_iterator_result
++resource_iterator_helper(void *res, void *user_data, uint32_t flags)
++{
++      struct wl_resource_iterator_context *context = user_data;
++      struct wl_resource *resource = res;
++
++      return context->it(resource, context->user_data);
++}
++
++/** Iterate over all the resources of a client
++ *
++ * \param client The client object
++ * \param iterator The iterator function
++ * \param user_data The user data pointer
++ *
++ * The function pointed by \a iterator will be called for each
++ * resource owned by the client. The \a user_data will be passed
++ * as the second argument of the iterator function.
++ * If the \a iterator function returns \a WL_ITERATOR_CONTINUE the iteration
++ * will continue, if it returns \a WL_ITERATOR_STOP it will stop.
++ *
++ * Creating and destroying resources while iterating is safe, but new
++ * resources may or may not be picked up by the iterator.
++ *
++ * \sa wl_iterator_result
++ *
++ * \memberof wl_client
++ */
++WL_EXPORT void
++wl_client_for_each_resource(struct wl_client *client,
++                          wl_client_for_each_resource_iterator_func_t iterator,
++                          void *user_data)
++{
++      struct wl_resource_iterator_context context = {
++              .user_data = user_data,
++              .it = iterator,
++      };
++
++      wl_map_for_each(&client->objects, resource_iterator_helper, &context);
++}
++
++static void
++handle_noop(struct wl_listener *listener, void *data)
++{
++      /* Do nothing */
++}
++
++/** Emits this signal, notifying all registered listeners.
++ *
++ * A safer version of wl_signal_emit() which can gracefully handle additions
++ * and deletions of any signal listener from within listener notification
++ * callbacks.
++ *
++ * Listeners deleted during a signal emission and which have not already been
++ * notified at the time of deletion are not notified by that emission.
++ *
++ * Listeners added (or readded) during signal emission are ignored by that
++ * emission.
++ *
++ * Note that repurposing a listener without explicitly removing it and readding
++ * it is not supported and can lead to unexpected behavior.
++ *
++ * \param signal The signal object that will emit the signal
++ * \param data The data that will be emitted with the signal
++ *
++ * \memberof wl_signal
++ * \since 1.20.90
++ */
++WL_EXPORT void
++wl_signal_emit_mutable(struct wl_signal *signal, void *data)
++{
++      struct wl_listener cursor;
++      struct wl_listener end;
++
++      /* Add two special markers: one cursor and one end marker. This way, we
++       * know that we've already called listeners on the left of the cursor
++       * and that we don't want to call listeners on the right of the end
++       * marker. The 'it' function can remove any element it wants from the
++       * list without troubles.
++       *
++       * There was a previous attempt that used to steal the whole list of
++       * listeners but then that broke wl_signal_get().
++       *
++       * wl_list_for_each_safe tries to be safe but it fails: it works fine
++       * if the current item is removed, but not if the next one is. */
++      wl_list_insert(&signal->listener_list, &cursor.link);
++      cursor.notify = handle_noop;
++      wl_list_insert(signal->listener_list.prev, &end.link);
++      end.notify = handle_noop;
++
++      while (cursor.link.next != &end.link) {
++              struct wl_list *pos = cursor.link.next;
++              struct wl_listener *l = wl_container_of(pos, l, link);
++
++              wl_list_remove(&cursor.link);
++              wl_list_insert(pos, &cursor.link);
++
++              l->notify(l, data);
++      }
++
++      wl_list_remove(&cursor.link);
++      wl_list_remove(&end.link);
++}
++
++/** \cond INTERNAL */
++
++/** Initialize a wl_priv_signal object
++ *
++ * wl_priv_signal is a safer implementation of a signal type, with the same API
++ * as wl_signal, but kept as a private utility of libwayland-server.
++ * It is safer because listeners can be removed from within wl_priv_signal_emit()
++ * without corrupting the signal's list.
++ *
++ * Before passing a wl_priv_signal object to any other function it must be
++ * initialized by using wl_priv_signal_init().
++ *
++ * \memberof wl_priv_signal
++ */
++void
++wl_priv_signal_init(struct wl_priv_signal *signal)
++{
++      wl_list_init(&signal->listener_list);
++      wl_list_init(&signal->emit_list);
++}
++
++/** Add a listener to a signal
++ *
++ * The new listener will be called when calling wl_signal_emit(). If a listener is
++ * added to the signal while wl_signal_emit() is running it will be called from
++ * the next time wl_priv_signal_emit() is called.
++ * To remove a listener call wl_list_remove() on its link member.
++ *
++ * \memberof wl_priv_signal
++ */
++void
++wl_priv_signal_add(struct wl_priv_signal *signal, struct wl_listener *listener)
++{
++      wl_list_insert(signal->listener_list.prev, &listener->link);
++}
++
++/** Get a listener added to a signal
++ *
++ * Returns the listener added to the given \a signal and with the given
++ * \a notify function, or NULL if there isn't any.
++ * Calling this function from within wl_priv_signal_emit() is safe and will
++ * return the correct value.
++ *
++ * \memberof wl_priv_signal
++ */
++struct wl_listener *
++wl_priv_signal_get(struct wl_priv_signal *signal, wl_notify_func_t notify)
++{
++      struct wl_listener *l;
++
++      wl_list_for_each(l, &signal->listener_list, link)
++              if (l->notify == notify)
++                      return l;
++      wl_list_for_each(l, &signal->emit_list, link)
++              if (l->notify == notify)
++                      return l;
++
++      return NULL;
++}
++
++/** Emit the signal, calling all the installed listeners
++ *
++ * Iterate over all the listeners added to this \a signal and call
++ * their \a notify function pointer, passing on the given \a data.
++ * Removing or adding a listener from within wl_priv_signal_emit()
++ * is safe.
++ */
++void
++wl_priv_signal_emit(struct wl_priv_signal *signal, void *data)
++{
++      struct wl_listener *l;
++      struct wl_list *pos;
++
++      wl_list_insert_list(&signal->emit_list, &signal->listener_list);
++      wl_list_init(&signal->listener_list);
++
++      /* Take every element out of the list and put them in a temporary list.
++       * This way, the 'it' func can remove any element it wants from the list
++       * without troubles, because we always get the first element, not the
++       * one after the current, which may be invalid.
++       * wl_list_for_each_safe tries to be safe but it fails: it works fine
++       * if the current item is removed, but not if the next one is. */
++      while (!wl_list_empty(&signal->emit_list)) {
++              pos = signal->emit_list.next;
++              l = wl_container_of(pos, l, link);
++
++              wl_list_remove(pos);
++              wl_list_insert(&signal->listener_list, pos);
++
++              l->notify(l, data);
++      }
++}
++
++/** Emit the signal for the last time, calling all the installed listeners
++ *
++ * Iterate over all the listeners added to this \a signal and call
++ * their \a notify function pointer, passing on the given \a data.
++ * Removing or adding a listener from within wl_priv_signal_emit()
++ * is safe, as is freeing the structure containing the listener.
++ *
++ * A large body of external code assumes it's ok to free a destruction
++ * listener without removing that listener from the list.  Mixing code
++ * that acts like this and code that doesn't will result in list
++ * corruption.
++ *
++ * We resolve this by removing each item from the list and isolating it
++ * in another list.  We discard it completely after firing the notifier.
++ * This should allow interoperability between code that unlinks its
++ * destruction listeners and code that just frees structures they're in.
++ *
++ */
++void
++wl_priv_signal_final_emit(struct wl_priv_signal *signal, void *data)
++{
++      struct wl_listener *l;
++      struct wl_list *pos;
++
++      /* During a destructor notifier isolate every list item before
++       * notifying.  This renders harmless the long standing misuse
++       * of freeing listeners without removing them, but allows
++       * callers that do choose to remove them to interoperate with
++       * ones that don't. */
++      while (!wl_list_empty(&signal->listener_list)) {
++              pos = signal->listener_list.next;
++              l = wl_container_of(pos, l, link);
++
++              wl_list_remove(pos);
++              wl_list_init(pos);
++
++              l->notify(l, data);
++      }
++}
++
++/** \endcond INTERNAL */
++
++/** \cond */ /* Deprecated functions below. */
++
++uint32_t
++wl_client_add_resource(struct wl_client *client,
++                     struct wl_resource *resource) WL_DEPRECATED;
++
++WL_EXPORT uint32_t
++wl_client_add_resource(struct wl_client *client,
++                     struct wl_resource *resource)
++{
++      if (resource->object.id == 0) {
++              resource->object.id =
++                      wl_map_insert_new(&client->objects,
++                                        WL_MAP_ENTRY_LEGACY, resource);
++              if (resource->object.id == 0)
++                      return 0;
++      } else if (wl_map_insert_at(&client->objects, WL_MAP_ENTRY_LEGACY,
++                                resource->object.id, resource) < 0) {
++              if (errno == EINVAL) {
++                      wl_resource_post_error(client->display_resource,
++                                             WL_DISPLAY_ERROR_INVALID_OBJECT,
++                                             "invalid new id %d",
++                                             resource->object.id);
++              }
++              return 0;
++      }
++
++      resource->client = client;
++      wl_signal_init(&resource->deprecated_destroy_signal);
++
++      return resource->object.id;
++}
++
++struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation,
++                   uint32_t id, void *data) WL_DEPRECATED;
++
++WL_EXPORT struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation, uint32_t id, void *data)
++{
++      struct wl_resource *resource;
++
++      resource = wl_resource_create(client, interface, -1, id);
++      if (resource == NULL)
++              wl_client_post_no_memory(client);
++      else
++              wl_resource_set_implementation(resource,
++                                             implementation, data, NULL);
++
++      return resource;
++}
++
++struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation, void *data) WL_DEPRECATED;
++
++WL_EXPORT struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation, void *data)
++{
++      struct wl_resource *resource;
++
++      resource = wl_resource_create(client, interface, -1, 0);
++      if (resource == NULL)
++              wl_client_post_no_memory(client);
++      else
++              wl_resource_set_implementation(resource,
++                                             implementation, data, NULL);
++
++      return resource;
++}
++
++struct wl_global *
++wl_display_add_global(struct wl_display *display,
++                    const struct wl_interface *interface,
++                    void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
++
++WL_EXPORT struct wl_global *
++wl_display_add_global(struct wl_display *display,
++                    const struct wl_interface *interface,
++                    void *data, wl_global_bind_func_t bind)
++{
++      return wl_global_create(display, interface, interface->version, data, bind);
++}
++
++void
++wl_display_remove_global(struct wl_display *display,
++                       struct wl_global *global) WL_DEPRECATED;
++
++WL_EXPORT void
++wl_display_remove_global(struct wl_display *display, struct wl_global *global)
++{
++      wl_global_destroy(global);
++}
++
++/** \endcond */
++
++/* Functions at the end of this file are deprecated.  Instead of adding new
++ * code here, add it before the comment above that states:
++ * Deprecated functions below.
++ */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1be565f23f7bf57b853893576fdd8cd702d6121b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,106 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file
++ *
++ *  \brief Include the server API, deprecations and protocol C API.
++ *
++ *  \warning Use of this header file is discouraged. Prefer including
++ *  wayland-server-core.h instead, which does not include the
++ *  server protocol header and as such only defines the library
++ *  API, excluding the deprecated API below.
++ */
++
++#ifndef WAYLAND_SERVER_H
++#define WAYLAND_SERVER_H
++
++#include <stdint.h>
++#include "wayland-server-core.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/*
++ * The user can set this macro to hide the wl_object, wl_resource and wl_buffer
++ * objects alongside the associated API.
++ *
++ * The structs were meant to be opaque, although we missed that in the early days.
++ *
++ * NOTE: the list of structs, functions, etc in this section MUST NEVER GROW.
++ * Otherwise we will break forward compatibility and applications that used to
++ * build fine will no longer be able to do so.
++ */
++#ifndef WL_HIDE_DEPRECATED
++
++struct wl_object {
++      const struct wl_interface *interface;
++      const void *implementation;
++      uint32_t id;
++};
++
++struct wl_resource {
++      struct wl_object object;
++      wl_resource_destroy_func_t destroy;
++      struct wl_list link;
++      struct wl_signal destroy_signal;
++      struct wl_client *client;
++      void *data;
++};
++
++uint32_t
++wl_client_add_resource(struct wl_client *client,
++                     struct wl_resource *resource) WL_DEPRECATED;
++
++struct wl_resource *
++wl_client_add_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation,
++                   uint32_t id, void *data) WL_DEPRECATED;
++
++struct wl_resource *
++wl_client_new_object(struct wl_client *client,
++                   const struct wl_interface *interface,
++                   const void *implementation, void *data) WL_DEPRECATED;
++
++struct wl_global *
++wl_display_add_global(struct wl_display *display,
++                    const struct wl_interface *interface,
++                    void *data,
++                    wl_global_bind_func_t bind) WL_DEPRECATED;
++
++void
++wl_display_remove_global(struct wl_display *display,
++                       struct wl_global *global) WL_DEPRECATED;
++
++#endif
++
++#ifdef  __cplusplus
++}
++#endif
++
++#include "wayland-server-protocol.h"
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c4cd390c44723c657ce765fec2ef60f0ccc78b38
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,706 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ *
++ * Authors:
++ *    Kristian Høgsberg <krh@bitplanet.net>
++ *    Benjamin Franzke <benjaminfranzke@googlemail.com>
++ *
++ */
++
++#define _GNU_SOURCE
++
++#include "config.h"
++
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <string.h>
++#include <sys/mman.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <assert.h>
++#include <signal.h>
++#include <pthread.h>
++#include <errno.h>
++#include <fcntl.h>
++
++#include "wayland-os.h"
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "wayland-server.h"
++
++/* This once_t is used to synchronize installing the SIGBUS handler
++ * and creating the TLS key. This will be done in the first call
++ * wl_shm_buffer_begin_access which can happen from any thread */
++static pthread_once_t wl_shm_sigbus_once = PTHREAD_ONCE_INIT;
++static pthread_key_t wl_shm_sigbus_data_key;
++static struct sigaction wl_shm_old_sigbus_action;
++
++struct wl_shm_pool {
++      struct wl_resource *resource;
++      int internal_refcount;
++      int external_refcount;
++      char *data;
++      ssize_t size;
++      ssize_t new_size;
++#ifndef MREMAP_MAYMOVE
++      /* The following three fields are needed for mremap() emulation. */
++      int mmap_fd;
++      int mmap_flags;
++      int mmap_prot;
++#endif
++      bool sigbus_is_impossible;
++};
++
++/** \class wl_shm_buffer
++ *
++ * \brief A SHM buffer
++ *
++ * wl_shm_buffer provides a helper for accessing the contents of a wl_buffer
++ * resource created via the wl_shm interface.
++ *
++ * A wl_shm_buffer becomes invalid as soon as its #wl_resource is destroyed.
++ */
++struct wl_shm_buffer {
++      struct wl_resource *resource;
++      int32_t width, height;
++      int32_t stride;
++      uint32_t format;
++      int offset;
++      struct wl_shm_pool *pool;
++};
++
++struct wl_shm_sigbus_data {
++      struct wl_shm_pool *current_pool;
++      int access_count;
++      int fallback_mapping_used;
++};
++
++static void *
++shm_pool_grow_mapping(struct wl_shm_pool *pool)
++{
++      void *data;
++
++#ifdef MREMAP_MAYMOVE
++      data = mremap(pool->data, pool->size, pool->new_size, MREMAP_MAYMOVE);
++#else
++      data = wl_os_mremap_maymove(pool->mmap_fd, pool->data, &pool->size,
++                                  pool->new_size, pool->mmap_prot,
++                                  pool->mmap_flags);
++      if (pool->size != 0) {
++              wl_resource_post_error(pool->resource,
++                                     WL_SHM_ERROR_INVALID_FD,
++                                     "leaked old mapping");
++      }
++#endif
++      return data;
++}
++
++static void
++shm_pool_finish_resize(struct wl_shm_pool *pool)
++{
++      void *data;
++
++      if (pool->size == pool->new_size)
++              return;
++
++      data = shm_pool_grow_mapping(pool);
++      if (data == MAP_FAILED) {
++              wl_resource_post_error(pool->resource,
++                                     WL_SHM_ERROR_INVALID_FD,
++                                     "failed mremap");
++              return;
++      }
++
++      pool->data = data;
++      pool->size = pool->new_size;
++}
++
++static void
++shm_pool_unref(struct wl_shm_pool *pool, bool external)
++{
++      if (external) {
++              pool->external_refcount--;
++              assert(pool->external_refcount >= 0);
++              if (pool->external_refcount == 0)
++                      shm_pool_finish_resize(pool);
++      } else {
++              pool->internal_refcount--;
++              assert(pool->internal_refcount >= 0);
++      }
++
++      if (pool->internal_refcount + pool->external_refcount > 0)
++              return;
++
++      munmap(pool->data, pool->size);
++#ifndef MREMAP_MAYMOVE
++      close(pool->mmap_fd);
++#endif
++      free(pool);
++}
++
++static void
++destroy_buffer(struct wl_resource *resource)
++{
++      struct wl_shm_buffer *buffer = wl_resource_get_user_data(resource);
++
++      shm_pool_unref(buffer->pool, false);
++      free(buffer);
++}
++
++static void
++shm_buffer_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++      wl_resource_destroy(resource);
++}
++
++static const struct wl_buffer_interface shm_buffer_interface = {
++      shm_buffer_destroy
++};
++
++static bool
++format_is_supported(struct wl_client *client, uint32_t format)
++{
++      struct wl_display *display = wl_client_get_display(client);
++      struct wl_array *formats;
++      uint32_t *p;
++
++      switch (format) {
++      case WL_SHM_FORMAT_ARGB8888:
++      case WL_SHM_FORMAT_XRGB8888:
++              return true;
++      default:
++              formats = wl_display_get_additional_shm_formats(display);
++              wl_array_for_each(p, formats)
++                      if (*p == format)
++                              return true;
++      }
++
++      return false;
++}
++
++static void
++shm_pool_create_buffer(struct wl_client *client, struct wl_resource *resource,
++                     uint32_t id, int32_t offset,
++                     int32_t width, int32_t height,
++                     int32_t stride, uint32_t format)
++{
++      struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++      struct wl_shm_buffer *buffer;
++
++      if (!format_is_supported(client, format)) {
++              wl_resource_post_error(resource,
++                                     WL_SHM_ERROR_INVALID_FORMAT,
++                                     "invalid format 0x%x", format);
++              return;
++      }
++
++      if (offset < 0 || width <= 0 || height <= 0 || stride < width ||
++          INT32_MAX / stride < height ||
++          offset > pool->size - stride * height) {
++              wl_resource_post_error(resource,
++                                     WL_SHM_ERROR_INVALID_STRIDE,
++                                     "invalid width, height or stride (%dx%d, %u)",
++                                     width, height, stride);
++              return;
++      }
++
++      buffer = zalloc(sizeof *buffer);
++      if (buffer == NULL) {
++              wl_client_post_no_memory(client);
++              return;
++      }
++
++      buffer->width = width;
++      buffer->height = height;
++      buffer->format = format;
++      buffer->stride = stride;
++      buffer->offset = offset;
++      buffer->pool = pool;
++      pool->internal_refcount++;
++
++      buffer->resource =
++              wl_resource_create(client, &wl_buffer_interface, 1, id);
++      if (buffer->resource == NULL) {
++              wl_client_post_no_memory(client);
++              shm_pool_unref(pool, false);
++              free(buffer);
++              return;
++      }
++
++      wl_resource_set_implementation(buffer->resource,
++                                     &shm_buffer_interface,
++                                     buffer, destroy_buffer);
++}
++
++static void
++destroy_pool(struct wl_resource *resource)
++{
++      struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++
++      shm_pool_unref(pool, false);
++}
++
++static void
++shm_pool_destroy(struct wl_client *client, struct wl_resource *resource)
++{
++      wl_resource_destroy(resource);
++}
++
++static void
++shm_pool_resize(struct wl_client *client, struct wl_resource *resource,
++              int32_t size)
++{
++      struct wl_shm_pool *pool = wl_resource_get_user_data(resource);
++
++      if (size < pool->size) {
++              wl_resource_post_error(resource,
++                                     WL_SHM_ERROR_INVALID_FD,
++                                     "shrinking pool invalid");
++              return;
++      }
++
++      pool->new_size = size;
++
++      /* If the compositor has taken references on this pool it
++       * may be caching pointers into it. In that case we
++       * defer the resize (which may move the entire mapping)
++       * until the compositor finishes dereferencing the pool.
++       */
++      if (pool->external_refcount == 0)
++              shm_pool_finish_resize(pool);
++}
++
++static const struct wl_shm_pool_interface shm_pool_interface = {
++      shm_pool_create_buffer,
++      shm_pool_destroy,
++      shm_pool_resize
++};
++
++static void
++shm_create_pool(struct wl_client *client, struct wl_resource *resource,
++              uint32_t id, int fd, int32_t size)
++{
++      struct wl_shm_pool *pool;
++      struct stat statbuf;
++      int seals;
++      int prot;
++      int flags;
++
++      if (size <= 0) {
++              wl_resource_post_error(resource,
++                                     WL_SHM_ERROR_INVALID_STRIDE,
++                                     "invalid size (%d)", size);
++              goto err_close;
++      }
++
++      pool = zalloc(sizeof *pool);
++      if (pool == NULL) {
++              wl_client_post_no_memory(client);
++              goto err_close;
++      }
++
++#ifdef HAVE_MEMFD_CREATE
++      seals = fcntl(fd, F_GET_SEALS);
++      if (seals == -1)
++              seals = 0;
++
++      if ((seals & F_SEAL_SHRINK) && fstat(fd, &statbuf) >= 0)
++              pool->sigbus_is_impossible = statbuf.st_size >= size;
++      else
++              pool->sigbus_is_impossible = false;
++#else
++      pool->sigbus_is_impossible = false;
++#endif
++
++      pool->internal_refcount = 1;
++      pool->external_refcount = 0;
++      pool->size = size;
++      pool->new_size = size;
++      prot = PROT_READ | PROT_WRITE;
++      flags = MAP_SHARED;
++      pool->data = mmap(NULL, size, prot, flags, fd, 0);
++      if (pool->data == MAP_FAILED) {
++              wl_resource_post_error(resource, WL_SHM_ERROR_INVALID_FD,
++                                     "failed mmap fd %d: %s", fd,
++                                     strerror(errno));
++              goto err_free;
++      }
++#ifndef MREMAP_MAYMOVE
++      /* We may need to keep the fd, prot and flags to emulate mremap(). */
++      pool->mmap_fd = fd;
++      pool->mmap_prot = prot;
++      pool->mmap_flags = flags;
++#else
++      close(fd);
++#endif
++      pool->resource =
++              wl_resource_create(client, &wl_shm_pool_interface, 1, id);
++      if (!pool->resource) {
++              wl_client_post_no_memory(client);
++              munmap(pool->data, pool->size);
++              free(pool);
++              return;
++      }
++
++      wl_resource_set_implementation(pool->resource,
++                                     &shm_pool_interface,
++                                     pool, destroy_pool);
++
++      return;
++
++err_free:
++      free(pool);
++err_close:
++      close(fd);
++}
++
++static const struct wl_shm_interface shm_interface = {
++      shm_create_pool
++};
++
++static void
++bind_shm(struct wl_client *client,
++       void *data, uint32_t version, uint32_t id)
++{
++      struct wl_resource *resource;
++      struct wl_display *display = wl_client_get_display(client);
++      struct wl_array *additional_formats;
++      uint32_t *p;
++
++      resource = wl_resource_create(client, &wl_shm_interface, 1, id);
++      if (!resource) {
++              wl_client_post_no_memory(client);
++              return;
++      }
++
++      wl_resource_set_implementation(resource, &shm_interface, data, NULL);
++
++      wl_shm_send_format(resource, WL_SHM_FORMAT_ARGB8888);
++      wl_shm_send_format(resource, WL_SHM_FORMAT_XRGB8888);
++
++      additional_formats = wl_display_get_additional_shm_formats(display);
++      wl_array_for_each(p, additional_formats)
++              wl_shm_send_format(resource, *p);
++}
++
++WL_EXPORT int
++wl_display_init_shm(struct wl_display *display)
++{
++      if (!wl_global_create(display, &wl_shm_interface, 1, NULL, bind_shm))
++              return -1;
++
++      return 0;
++}
++
++WL_EXPORT struct wl_shm_buffer *
++wl_shm_buffer_get(struct wl_resource *resource)
++{
++      if (resource == NULL)
++              return NULL;
++
++      if (wl_resource_instance_of(resource, &wl_buffer_interface,
++                                  &shm_buffer_interface))
++              return wl_resource_get_user_data(resource);
++      else
++              return NULL;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_stride(struct wl_shm_buffer *buffer)
++{
++      return buffer->stride;
++}
++
++
++/** Get a pointer to the memory for the SHM buffer
++ *
++ * \param buffer The buffer object
++ *
++ * Returns a pointer which can be used to read the data contained in
++ * the given SHM buffer.
++ *
++ * As this buffer is memory-mapped, reading from it may generate
++ * SIGBUS signals. This can happen if the client claims that the
++ * buffer is larger than it is or if something truncates the
++ * underlying file. To prevent this signal from causing the compositor
++ * to crash you should call wl_shm_buffer_begin_access and
++ * wl_shm_buffer_end_access around code that reads from the memory.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void *
++wl_shm_buffer_get_data(struct wl_shm_buffer *buffer)
++{
++      if (buffer->pool->external_refcount &&
++          (buffer->pool->size != buffer->pool->new_size))
++              wl_log("Buffer address requested when its parent pool "
++                     "has an external reference and a deferred resize "
++                     "pending.\n");
++      return buffer->pool->data + buffer->offset;
++}
++
++WL_EXPORT uint32_t
++wl_shm_buffer_get_format(struct wl_shm_buffer *buffer)
++{
++      return buffer->format;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_width(struct wl_shm_buffer *buffer)
++{
++      return buffer->width;
++}
++
++WL_EXPORT int32_t
++wl_shm_buffer_get_height(struct wl_shm_buffer *buffer)
++{
++      return buffer->height;
++}
++
++/** Get a reference to a shm_buffer's shm_pool
++ *
++ * \param buffer The buffer object
++ *
++ * Returns a pointer to a buffer's shm_pool and increases the
++ * shm_pool refcount.
++ *
++ * The compositor must remember to call wl_shm_pool_unref when
++ * it no longer needs the reference to ensure proper destruction
++ * of the pool.
++ *
++ * \memberof wl_shm_buffer
++ * \sa wl_shm_pool_unref
++ */
++WL_EXPORT struct wl_shm_pool *
++wl_shm_buffer_ref_pool(struct wl_shm_buffer *buffer)
++{
++      assert(buffer->pool->internal_refcount +
++             buffer->pool->external_refcount);
++
++      buffer->pool->external_refcount++;
++      return buffer->pool;
++}
++
++/** Unreference a shm_pool
++ *
++ * \param pool The pool object
++ *
++ * Drops a reference to a wl_shm_pool object.
++ *
++ * This is only necessary if the compositor has explicitly
++ * taken a reference with wl_shm_buffer_ref_pool(), otherwise
++ * the pool will be automatically destroyed when appropriate.
++ *
++ * \memberof wl_shm_pool
++ * \sa wl_shm_buffer_ref_pool
++ */
++WL_EXPORT void
++wl_shm_pool_unref(struct wl_shm_pool *pool)
++{
++      shm_pool_unref(pool, true);
++}
++
++static void
++reraise_sigbus(void)
++{
++      /* If SIGBUS is raised for some other reason than accessing
++       * the pool then we'll uninstall the signal handler so we can
++       * reraise it. This would presumably kill the process */
++      sigaction(SIGBUS, &wl_shm_old_sigbus_action, NULL);
++      raise(SIGBUS);
++}
++
++static void
++sigbus_handler(int signum, siginfo_t *info, void *context)
++{
++      struct wl_shm_sigbus_data *sigbus_data =
++              pthread_getspecific(wl_shm_sigbus_data_key);
++      struct wl_shm_pool *pool;
++
++      if (sigbus_data == NULL) {
++              reraise_sigbus();
++              return;
++      }
++
++      pool = sigbus_data->current_pool;
++
++      /* If the offending address is outside the mapped space for
++       * the pool then the error is a real problem so we'll reraise
++       * the signal */
++      if (pool == NULL ||
++          (char *) info->si_addr < pool->data ||
++          (char *) info->si_addr >= pool->data + pool->size) {
++              reraise_sigbus();
++              return;
++      }
++
++      sigbus_data->fallback_mapping_used = 1;
++
++      /* This should replace the previous mapping */
++      if (mmap(pool->data, pool->size, PROT_READ | PROT_WRITE,
++               MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, 0, 0) == MAP_FAILED) {
++              reraise_sigbus();
++              return;
++      }
++}
++
++static void
++destroy_sigbus_data(void *data)
++{
++      struct wl_shm_sigbus_data *sigbus_data = data;
++
++      free(sigbus_data);
++}
++
++static void
++init_sigbus_data_key(void)
++{
++      struct sigaction new_action = {
++              .sa_sigaction = sigbus_handler,
++              .sa_flags = SA_SIGINFO | SA_NODEFER
++      };
++
++      sigemptyset(&new_action.sa_mask);
++
++      sigaction(SIGBUS, &new_action, &wl_shm_old_sigbus_action);
++
++      pthread_key_create(&wl_shm_sigbus_data_key, destroy_sigbus_data);
++}
++
++/** Mark that the given SHM buffer is about to be accessed
++ *
++ * \param buffer The SHM buffer
++ *
++ * An SHM buffer is a memory-mapped file given by the client.
++ * According to POSIX, reading from a memory-mapped region that
++ * extends off the end of the file will cause a SIGBUS signal to be
++ * generated. Normally this would cause the compositor to terminate.
++ * In order to make the compositor robust against clients that change
++ * the size of the underlying file or lie about its size, you should
++ * protect access to the buffer by calling this function before
++ * reading from the memory and call wl_shm_buffer_end_access
++ * afterwards. This will install a signal handler for SIGBUS which
++ * will prevent the compositor from crashing.
++ *
++ * After calling this function the signal handler will remain
++ * installed for the lifetime of the compositor process. Note that
++ * this function will not work properly if the compositor is also
++ * installing its own handler for SIGBUS.
++ *
++ * If a SIGBUS signal is received for an address within the range of
++ * the SHM pool of the given buffer then the client will be sent an
++ * error event when wl_shm_buffer_end_access is called. If the signal
++ * is for an address outside that range then the signal handler will
++ * reraise the signal which would will likely cause the compositor to
++ * terminate.
++ *
++ * It is safe to nest calls to these functions as long as the nested
++ * calls are all accessing the same buffer. The number of calls to
++ * wl_shm_buffer_end_access must match the number of calls to
++ * wl_shm_buffer_begin_access. These functions are thread-safe and it
++ * is allowed to simultaneously access different buffers or the same
++ * buffer from multiple threads.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void
++wl_shm_buffer_begin_access(struct wl_shm_buffer *buffer)
++{
++      struct wl_shm_pool *pool = buffer->pool;
++      struct wl_shm_sigbus_data *sigbus_data;
++
++      if (pool->sigbus_is_impossible)
++              return;
++
++      pthread_once(&wl_shm_sigbus_once, init_sigbus_data_key);
++
++      sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
++      if (sigbus_data == NULL) {
++              sigbus_data = zalloc(sizeof *sigbus_data);
++              if (sigbus_data == NULL)
++                      return;
++
++              pthread_setspecific(wl_shm_sigbus_data_key, sigbus_data);
++      }
++
++      assert(sigbus_data->current_pool == NULL ||
++             sigbus_data->current_pool == pool);
++
++      sigbus_data->current_pool = pool;
++      sigbus_data->access_count++;
++}
++
++/** Ends the access to a buffer started by wl_shm_buffer_begin_access
++ *
++ * \param buffer The SHM buffer
++ *
++ * This should be called after wl_shm_buffer_begin_access once the
++ * buffer is no longer being accessed. If a SIGBUS signal was
++ * generated in-between these two calls then the resource for the
++ * given buffer will be sent an error.
++ *
++ * \memberof wl_shm_buffer
++ */
++WL_EXPORT void
++wl_shm_buffer_end_access(struct wl_shm_buffer *buffer)
++{
++      struct wl_shm_pool *pool = buffer->pool;
++      struct wl_shm_sigbus_data *sigbus_data;
++
++      if (pool->sigbus_is_impossible)
++              return;
++
++      sigbus_data = pthread_getspecific(wl_shm_sigbus_data_key);
++      assert(sigbus_data && sigbus_data->access_count >= 1);
++
++      if (--sigbus_data->access_count == 0) {
++              if (sigbus_data->fallback_mapping_used) {
++                      wl_resource_post_error(buffer->resource,
++                                             WL_SHM_ERROR_INVALID_FD,
++                                             "error accessing SHM buffer");
++                      sigbus_data->fallback_mapping_used = 0;
++              }
++
++              sigbus_data->current_pool = NULL;
++      }
++}
++
++/** \cond */ /* Deprecated functions below. */
++
++WL_EXPORT struct wl_shm_buffer *
++wl_shm_buffer_create(struct wl_client *client,
++                   uint32_t id, int32_t width, int32_t height,
++                   int32_t stride, uint32_t format)
++{
++      return NULL;
++}
++
++/** \endcond */
++
++/* Functions at the end of this file are deprecated.  Instead of adding new
++ * code here, add it before the comment above that states:
++ * Deprecated functions below.
++ */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bb2a1838f1e8d20289845ab8c0147ba1bfe42028
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,465 @@@
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2011 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <errno.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdarg.h>
++
++#include "wayland-util.h"
++#include "wayland-private.h"
++
++WL_EXPORT void
++wl_list_init(struct wl_list *list)
++{
++      list->prev = list;
++      list->next = list;
++}
++
++WL_EXPORT void
++wl_list_insert(struct wl_list *list, struct wl_list *elm)
++{
++      elm->prev = list;
++      elm->next = list->next;
++      list->next = elm;
++      elm->next->prev = elm;
++}
++
++WL_EXPORT void
++wl_list_remove(struct wl_list *elm)
++{
++      elm->prev->next = elm->next;
++      elm->next->prev = elm->prev;
++      elm->next = NULL;
++      elm->prev = NULL;
++}
++
++WL_EXPORT int
++wl_list_length(const struct wl_list *list)
++{
++      struct wl_list *e;
++      int count;
++
++      count = 0;
++      e = list->next;
++      while (e != list) {
++              e = e->next;
++              count++;
++      }
++
++      return count;
++}
++
++WL_EXPORT int
++wl_list_empty(const struct wl_list *list)
++{
++      return list->next == list;
++}
++
++WL_EXPORT void
++wl_list_insert_list(struct wl_list *list, struct wl_list *other)
++{
++      if (wl_list_empty(other))
++              return;
++
++      other->next->prev = list;
++      other->prev->next = list->next;
++      list->next->prev = other->prev;
++      list->next = other->next;
++}
++
++WL_EXPORT void
++wl_array_init(struct wl_array *array)
++{
++      memset(array, 0, sizeof *array);
++}
++
++WL_EXPORT void
++wl_array_release(struct wl_array *array)
++{
++      free(array->data);
++      array->data = WL_ARRAY_POISON_PTR;
++}
++
++WL_EXPORT void *
++wl_array_add(struct wl_array *array, size_t size)
++{
++      size_t alloc;
++      void *data, *p;
++
++      if (array->alloc > 0)
++              alloc = array->alloc;
++      else
++              alloc = 16;
++
++      while (alloc < array->size + size)
++              alloc *= 2;
++
++      if (array->alloc < alloc) {
++              if (array->alloc > 0)
++                      data = realloc(array->data, alloc);
++              else
++                      data = malloc(alloc);
++
++              if (data == NULL)
++                      return NULL;
++              array->data = data;
++              array->alloc = alloc;
++      }
++
++      p = (char *)array->data + array->size;
++      array->size += size;
++
++      return p;
++}
++
++WL_EXPORT int
++wl_array_copy(struct wl_array *array, struct wl_array *source)
++{
++      if (array->size < source->size) {
++              if (!wl_array_add(array, source->size - array->size))
++                      return -1;
++      } else {
++              array->size = source->size;
++      }
++
++      if (source->size > 0)
++              memcpy(array->data, source->data, source->size);
++
++      return 0;
++}
++
++/** \cond */
++
++int
++wl_interface_equal(const struct wl_interface *a, const struct wl_interface *b)
++{
++      /* In most cases the pointer equality test is sufficient.
++       * However, in some cases, depending on how things are split
++       * across shared objects, we can end up with multiple
++       * instances of the interface metadata constants.  So if the
++       * pointers match, the interfaces are equal, if they don't
++       * match we have to compare the interface names.
++       */
++      return a == b || strcmp(a->name, b->name) == 0;
++}
++
++union map_entry {
++      uintptr_t next;
++      void *data;
++};
++
++#define map_entry_is_free(entry) ((entry).next & 0x1)
++#define map_entry_get_data(entry) ((void *)((entry).next & ~(uintptr_t)0x3))
++#define map_entry_get_flags(entry) (((entry).next >> 1) & 0x1)
++
++void
++wl_map_init(struct wl_map *map, uint32_t side)
++{
++      memset(map, 0, sizeof *map);
++      map->side = side;
++}
++
++void
++wl_map_release(struct wl_map *map)
++{
++      wl_array_release(&map->client_entries);
++      wl_array_release(&map->server_entries);
++}
++
++uint32_t
++wl_map_insert_new(struct wl_map *map, uint32_t flags, void *data)
++{
++      union map_entry *start, *entry;
++      struct wl_array *entries;
++      uint32_t base;
++      uint32_t count;
++
++      if (map->side == WL_MAP_CLIENT_SIDE) {
++              entries = &map->client_entries;
++              base = 0;
++      } else {
++              entries = &map->server_entries;
++              base = WL_SERVER_ID_START;
++      }
++
++      if (map->free_list) {
++              start = entries->data;
++              entry = &start[map->free_list >> 1];
++              map->free_list = entry->next;
++      } else {
++              entry = wl_array_add(entries, sizeof *entry);
++              if (!entry)
++                      return 0;
++              start = entries->data;
++      }
++
++      /* wl_array only grows, so if we have too many objects at
++       * this point there's no way to clean up. We could be more
++       * pro-active about trying to avoid this allocation, but
++       * it doesn't really matter because at this point there is
++       * nothing to be done but disconnect the client and delete
++       * the whole array either way.
++       */
++      count = entry - start;
++      if (count > WL_MAP_MAX_OBJECTS) {
++              /* entry->data is freshly malloced garbage, so we'd
++               * better make it a NULL so wl_map_for_each doesn't
++               * dereference it later. */
++              entry->data = NULL;
++              errno = ENOSPC;
++              return 0;
++      }
++      entry->data = data;
++      entry->next |= (flags & 0x1) << 1;
++
++      return count + base;
++}
++
++int
++wl_map_insert_at(struct wl_map *map, uint32_t flags, uint32_t i, void *data)
++{
++      union map_entry *start;
++      uint32_t count;
++      struct wl_array *entries;
++
++      if (i < WL_SERVER_ID_START) {
++              entries = &map->client_entries;
++      } else {
++              entries = &map->server_entries;
++              i -= WL_SERVER_ID_START;
++      }
++
++      if (i > WL_MAP_MAX_OBJECTS) {
++              errno = ENOSPC;
++              return -1;
++      }
++
++      count = entries->size / sizeof *start;
++      if (count < i) {
++              errno = EINVAL;
++              return -1;
++      }
++
++      if (count == i) {
++              if (!wl_array_add(entries, sizeof *start))
++                      return -1;
++      }
++
++      start = entries->data;
++      start[i].data = data;
++      start[i].next |= (flags & 0x1) << 1;
++
++      return 0;
++}
++
++int
++wl_map_reserve_new(struct wl_map *map, uint32_t i)
++{
++      union map_entry *start;
++      uint32_t count;
++      struct wl_array *entries;
++
++      if (i < WL_SERVER_ID_START) {
++              if (map->side == WL_MAP_CLIENT_SIDE) {
++                      errno = EINVAL;
++                      return -1;
++              }
++
++              entries = &map->client_entries;
++      } else {
++              if (map->side == WL_MAP_SERVER_SIDE) {
++                      errno = EINVAL;
++                      return -1;
++              }
++
++              entries = &map->server_entries;
++              i -= WL_SERVER_ID_START;
++      }
++
++      if (i > WL_MAP_MAX_OBJECTS) {
++              errno = ENOSPC;
++              return -1;
++      }
++
++      count = entries->size / sizeof *start;
++      if (count < i) {
++              errno = EINVAL;
++              return -1;
++      }
++
++      if (count == i) {
++              if (!wl_array_add(entries, sizeof *start))
++                      return -1;
++
++              start = entries->data;
++              start[i].data = NULL;
++      } else {
++              start = entries->data;
++              if (start[i].data != NULL) {
++                      errno = EINVAL;
++                      return -1;
++              }
++      }
++
++      return 0;
++}
++
++void
++wl_map_remove(struct wl_map *map, uint32_t i)
++{
++      union map_entry *start;
++      struct wl_array *entries;
++
++      if (i < WL_SERVER_ID_START) {
++              if (map->side == WL_MAP_SERVER_SIDE)
++                      return;
++
++              entries = &map->client_entries;
++      } else {
++              if (map->side == WL_MAP_CLIENT_SIDE)
++                      return;
++
++              entries = &map->server_entries;
++              i -= WL_SERVER_ID_START;
++      }
++
++      start = entries->data;
++      start[i].next = map->free_list;
++      map->free_list = (i << 1) | 1;
++}
++
++void *
++wl_map_lookup(struct wl_map *map, uint32_t i)
++{
++      union map_entry *start;
++      uint32_t count;
++      struct wl_array *entries;
++
++      if (i < WL_SERVER_ID_START) {
++              entries = &map->client_entries;
++      } else {
++              entries = &map->server_entries;
++              i -= WL_SERVER_ID_START;
++      }
++
++      start = entries->data;
++      count = entries->size / sizeof *start;
++
++      if (i < count && !map_entry_is_free(start[i]))
++              return map_entry_get_data(start[i]);
++
++      return NULL;
++}
++
++uint32_t
++wl_map_lookup_flags(struct wl_map *map, uint32_t i)
++{
++      union map_entry *start;
++      uint32_t count;
++      struct wl_array *entries;
++
++      if (i < WL_SERVER_ID_START) {
++              entries = &map->client_entries;
++      } else {
++              entries = &map->server_entries;
++              i -= WL_SERVER_ID_START;
++      }
++
++      start = entries->data;
++      count = entries->size / sizeof *start;
++
++      if (i < count && !map_entry_is_free(start[i]))
++              return map_entry_get_flags(start[i]);
++
++      return 0;
++}
++
++static enum wl_iterator_result
++for_each_helper(struct wl_array *entries, wl_iterator_func_t func, void *data)
++{
++      enum wl_iterator_result ret = WL_ITERATOR_CONTINUE;
++      union map_entry entry, *start;
++      size_t count;
++
++      start = (union map_entry *) entries->data;
++      count = entries->size / sizeof(union map_entry);
++
++      for (size_t idx = 0; idx < count; idx++) {
++              entry = start[idx];
++              if (entry.data && !map_entry_is_free(entry)) {
++                      ret = func(map_entry_get_data(entry), data, map_entry_get_flags(entry));
++                      if (ret != WL_ITERATOR_CONTINUE)
++                              break;
++              }
++      }
++
++      return ret;
++}
++
++void
++wl_map_for_each(struct wl_map *map, wl_iterator_func_t func, void *data)
++{
++      enum wl_iterator_result ret;
++
++      ret = for_each_helper(&map->client_entries, func, data);
++      if (ret == WL_ITERATOR_CONTINUE)
++              for_each_helper(&map->server_entries, func, data);
++}
++
++static void
++wl_log_stderr_handler(const char *fmt, va_list arg)
++{
++      vfprintf(stderr, fmt, arg);
++}
++
++wl_log_func_t wl_log_handler = wl_log_stderr_handler;
++
++void
++wl_log(const char *fmt, ...)
++{
++      va_list argp;
++
++      va_start(argp, fmt);
++      wl_log_handler(fmt, argp);
++      va_end(argp);
++}
++
++void
++wl_abort(const char *fmt, ...)
++{
++      va_list argp;
++
++      va_start(argp, fmt);
++      wl_log_handler(fmt, argp);
++      va_end(argp);
++
++      abort();
++}
++
++/** \endcond */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..4d59231fa69f99a4c8df675cc6fec6aa37d354b3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,765 @@@
++/*
++ * Copyright © 2008 Kristian Høgsberg
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++/** \file wayland-util.h
++ *
++ * \brief Utility classes, functions, and macros.
++ */
++
++#ifndef WAYLAND_UTIL_H
++#define WAYLAND_UTIL_H
++
++#include <math.h>
++#include <stddef.h>
++#include <inttypes.h>
++#include <stdarg.h>
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/** Visibility attribute */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_EXPORT __attribute__ ((visibility("default")))
++#else
++#define WL_EXPORT
++#endif
++
++/** Deprecated attribute */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_DEPRECATED __attribute__ ((deprecated))
++#else
++#define WL_DEPRECATED
++#endif
++
++/**
++ * Printf-style argument attribute
++ *
++ * \param x Ordinality of the format string argument
++ * \param y Ordinality of the argument to check against the format string
++ *
++ * \sa https://gcc.gnu.org/onlinedocs/gcc-3.2.1/gcc/Function-Attributes.html
++ */
++#if defined(__GNUC__) && __GNUC__ >= 4
++#define WL_PRINTF(x, y) __attribute__((__format__(__printf__, x, y)))
++#else
++#define WL_PRINTF(x, y)
++#endif
++
++/** \class wl_object
++ *
++ * \brief A protocol object.
++ *
++ * A `wl_object` is an opaque struct identifying the protocol object
++ * underlying a `wl_proxy` or `wl_resource`.
++ *
++ * \note Functions accessing a `wl_object` are not normally used by client code.
++ * Clients should normally use the higher level interface generated by the
++ * scanner to interact with compositor objects.
++ *
++ */
++struct wl_object;
++
++/**
++ * Protocol message signature
++ *
++ * A wl_message describes the signature of an actual protocol message, such as a
++ * request or event, that adheres to the Wayland protocol wire format. The
++ * protocol implementation uses a wl_message within its demarshal machinery for
++ * decoding messages between a compositor and its clients. In a sense, a
++ * wl_message is to a protocol message like a class is to an object.
++ *
++ * The `name` of a wl_message is the name of the corresponding protocol message.
++ *
++ * The `signature` is an ordered list of symbols representing the data types
++ * of message arguments and, optionally, a protocol version and indicators for
++ * nullability. A leading integer in the `signature` indicates the _since_
++ * version of the protocol message. A `?` preceding a data type symbol indicates
++ * that the following argument type is nullable. While it is a protocol violation
++ * to send messages with non-nullable arguments set to `NULL`, event handlers in
++ * clients might still get called with non-nullable object arguments set to
++ * `NULL`. This can happen when the client destroyed the object being used as
++ * argument on its side and an event referencing that object was sent before the
++ * server knew about its destruction. As this race cannot be prevented, clients
++ * should - as a general rule - program their event handlers such that they can
++ * handle object arguments declared non-nullable being `NULL` gracefully.
++ *
++ * When no arguments accompany a message, `signature` is an empty string.
++ *
++ * Symbols:
++ *
++ * * `i`: int
++ * * `u`: uint
++ * * `f`: fixed
++ * * `s`: string
++ * * `o`: object
++ * * `n`: new_id
++ * * `a`: array
++ * * `h`: fd
++ * * `?`: following argument (`o` or `s`) is nullable
++ *
++ * While demarshaling primitive arguments is straightforward, when demarshaling
++ * messages containing `object` or `new_id` arguments, the protocol
++ * implementation often must determine the type of the object. The `types` of a
++ * wl_message is an array of wl_interface references that correspond to `o` and
++ * `n` arguments in `signature`, with `NULL` placeholders for arguments with
++ * non-object types.
++ *
++ * Consider the protocol event wl_display `delete_id` that has a single `uint`
++ * argument. The wl_message is:
++ *
++ * \code
++ * { "delete_id", "u", [NULL] }
++ * \endcode
++ *
++ * Here, the message `name` is `"delete_id"`, the `signature` is `"u"`, and the
++ * argument `types` is `[NULL]`, indicating that the `uint` argument has no
++ * corresponding wl_interface since it is a primitive argument.
++ *
++ * In contrast, consider a `wl_foo` interface supporting protocol request `bar`
++ * that has existed since version 2, and has two arguments: a `uint` and an
++ * object of type `wl_baz_interface` that may be `NULL`. Such a `wl_message`
++ * might be:
++ *
++ * \code
++ * { "bar", "2u?o", [NULL, &wl_baz_interface] }
++ * \endcode
++ *
++ * Here, the message `name` is `"bar"`, and the `signature` is `"2u?o"`. Notice
++ * how the `2` indicates the protocol version, the `u` indicates the first
++ * argument type is `uint`, and the `?o` indicates that the second argument
++ * is an object that may be `NULL`. Lastly, the argument `types` array indicates
++ * that no wl_interface corresponds to the first argument, while the type
++ * `wl_baz_interface` corresponds to the second argument.
++ *
++ * \sa wl_argument
++ * \sa wl_interface
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Wire-Format">Wire Format</a>
++ */
++struct wl_message {
++      /** Message name */
++      const char *name;
++      /** Message signature */
++      const char *signature;
++      /** Object argument interfaces */
++      const struct wl_interface **types;
++};
++
++/**
++ * Protocol object interface
++ *
++ * A wl_interface describes the API of a protocol object defined in the Wayland
++ * protocol specification. The protocol implementation uses a wl_interface
++ * within its marshalling machinery for encoding client requests.
++ *
++ * The `name` of a wl_interface is the name of the corresponding protocol
++ * interface, and `version` represents the version of the interface. The members
++ * `method_count` and `event_count` represent the number of `methods` (requests)
++ * and `events` in the respective wl_message members.
++ *
++ * For example, consider a protocol interface `foo`, marked as version `1`, with
++ * two requests and one event.
++ *
++ * \code{.xml}
++ * <interface name="foo" version="1">
++ *   <request name="a"></request>
++ *   <request name="b"></request>
++ *   <event name="c"></event>
++ * </interface>
++ * \endcode
++ *
++ * Given two wl_message arrays `foo_requests` and `foo_events`, a wl_interface
++ * for `foo` might be:
++ *
++ * \code
++ * struct wl_interface foo_interface = {
++ *         "foo", 1,
++ *         2, foo_requests,
++ *         1, foo_events
++ * };
++ * \endcode
++ *
++ * \note The server side of the protocol may define interface <em>implementation
++ *       types</em> that incorporate the term `interface` in their name. Take
++ *       care to not confuse these server-side `struct`s with a wl_interface
++ *       variable whose name also ends in `interface`. For example, while the
++ *       server may define a type `struct wl_foo_interface`, the client may
++ *       define a `struct wl_interface wl_foo_interface`.
++ *
++ * \sa wl_message
++ * \sa wl_proxy
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Interfaces">Interfaces</a>
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-Versioning">Versioning</a>
++ */
++struct wl_interface {
++      /** Interface name */
++      const char *name;
++      /** Interface version */
++      int version;
++      /** Number of methods (requests) */
++      int method_count;
++      /** Method (request) signatures */
++      const struct wl_message *methods;
++      /** Number of events */
++      int event_count;
++      /** Event signatures */
++      const struct wl_message *events;
++};
++
++/** \class wl_list
++ *
++ * \brief Doubly-linked list
++ *
++ * On its own, an instance of `struct wl_list` represents the sentinel head of
++ * a doubly-linked list, and must be initialized using wl_list_init().
++ * When empty, the list head's `next` and `prev` members point to the list head
++ * itself, otherwise `next` references the first element in the list, and `prev`
++ * refers to the last element in the list.
++ *
++ * Use the `struct wl_list` type to represent both the list head and the links
++ * between elements within the list. Use wl_list_empty() to determine if the
++ * list is empty in O(1).
++ *
++ * All elements in the list must be of the same type. The element type must have
++ * a `struct wl_list` member, often named `link` by convention. Prior to
++ * insertion, there is no need to initialize an element's `link` - invoking
++ * wl_list_init() on an individual list element's `struct wl_list` member is
++ * unnecessary if the very next operation is wl_list_insert(). However, a
++ * common idiom is to initialize an element's `link` prior to removal - ensure
++ * safety by invoking wl_list_init() before wl_list_remove().
++ *
++ * Consider a list reference `struct wl_list foo_list`, an element type as
++ * `struct element`, and an element's link member as `struct wl_list link`.
++ *
++ * The following code initializes a list and adds three elements to it.
++ *
++ * \code
++ * struct wl_list foo_list;
++ *
++ * struct element {
++ *         int foo;
++ *         struct wl_list link;
++ * };
++ * struct element e1, e2, e3;
++ *
++ * wl_list_init(&foo_list);
++ * wl_list_insert(&foo_list, &e1.link);   // e1 is the first element
++ * wl_list_insert(&foo_list, &e2.link);   // e2 is now the first element
++ * wl_list_insert(&e2.link, &e3.link); // insert e3 after e2
++ * \endcode
++ *
++ * The list now looks like <em>[e2, e3, e1]</em>.
++ *
++ * The `wl_list` API provides some iterator macros. For example, to iterate
++ * a list in ascending order:
++ *
++ * \code
++ * struct element *e;
++ * wl_list_for_each(e, foo_list, link) {
++ *         do_something_with_element(e);
++ * }
++ * \endcode
++ *
++ * See the documentation of each iterator for details.
++ * \sa http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/include/linux/list.h
++ */
++struct wl_list {
++      /** Previous list element */
++      struct wl_list *prev;
++      /** Next list element */
++      struct wl_list *next;
++};
++
++/**
++ * Initializes the list.
++ *
++ * \param list List to initialize
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_init(struct wl_list *list);
++
++/**
++ * Inserts an element into the list, after the element represented by \p list.
++ * When \p list is a reference to the list itself (the head), set the containing
++ * struct of \p elm as the first element in the list.
++ *
++ * \note If \p elm is already part of a list, inserting it again will lead to
++ *       list corruption.
++ *
++ * \param list List element after which the new element is inserted
++ * \param elm Link of the containing struct to insert into the list
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_insert(struct wl_list *list, struct wl_list *elm);
++
++/**
++ * Removes an element from the list.
++ *
++ * \note This operation leaves \p elm in an invalid state.
++ *
++ * \param elm Link of the containing struct to remove from the list
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_remove(struct wl_list *elm);
++
++/**
++ * Determines the length of the list.
++ *
++ * \note This is an O(n) operation.
++ *
++ * \param list List whose length is to be determined
++ *
++ * \return Number of elements in the list
++ *
++ * \memberof wl_list
++ */
++int
++wl_list_length(const struct wl_list *list);
++
++/**
++ * Determines if the list is empty.
++ *
++ * \param list List whose emptiness is to be determined
++ *
++ * \return 1 if empty, or 0 if not empty
++ *
++ * \memberof wl_list
++ */
++int
++wl_list_empty(const struct wl_list *list);
++
++/**
++ * Inserts all of the elements of one list into another, after the element
++ * represented by \p list.
++ *
++ * \note This leaves \p other in an invalid state.
++ *
++ * \param list List element after which the other list elements will be inserted
++ * \param other List of elements to insert
++ *
++ * \memberof wl_list
++ */
++void
++wl_list_insert_list(struct wl_list *list, struct wl_list *other);
++
++/**
++ * Retrieves a pointer to a containing struct, given a member name.
++ *
++ * This macro allows "conversion" from a pointer to a member to its containing
++ * struct. This is useful if you have a contained item like a wl_list,
++ * wl_listener, or wl_signal, provided via a callback or other means, and would
++ * like to retrieve the struct that contains it.
++ *
++ * To demonstrate, the following example retrieves a pointer to
++ * `example_container` given only its `destroy_listener` member:
++ *
++ * \code
++ * struct example_container {
++ *         struct wl_listener destroy_listener;
++ *         // other members...
++ * };
++ *
++ * void example_container_destroy(struct wl_listener *listener, void *data)
++ * {
++ *         struct example_container *ctr;
++ *
++ *         ctr = wl_container_of(listener, ctr, destroy_listener);
++ *         // destroy ctr...
++ * }
++ * \endcode
++ *
++ * \note `sample` need not be a valid pointer. A null or uninitialised pointer
++ *       is sufficient.
++ *
++ * \param ptr Valid pointer to the contained member
++ * \param sample Pointer to a struct whose type contains \p ptr
++ * \param member Named location of \p ptr within the \p sample type
++ *
++ * \return The container for the specified pointer
++ */
++#define wl_container_of(ptr, sample, member)                          \
++      (__typeof__(sample))((char *)(ptr) -                            \
++                           offsetof(__typeof__(*sample), member))
++
++/**
++ * Iterates over a list.
++ *
++ * This macro expresses a for-each iterator for wl_list. Given a list and
++ * wl_list link member name (often named `link` by convention), this macro
++ * assigns each element in the list to \p pos, which can then be referenced in
++ * a trailing code block. For example, given a wl_list of `struct message`
++ * elements:
++ *
++ * \code
++ * struct message {
++ *         char *contents;
++ *         wl_list link;
++ * };
++ *
++ * struct wl_list *message_list;
++ * // Assume message_list now "contains" many messages
++ *
++ * struct message *m;
++ * wl_list_for_each(m, message_list, link) {
++ *         do_something_with_message(m);
++ * }
++ * \endcode
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each(pos, head, member)                           \
++      for (pos = wl_container_of((head)->next, pos, member);  \
++           &pos->member != (head);                                    \
++           pos = wl_container_of(pos->member.next, pos, member))
++
++/**
++ * Iterates over a list, safe against removal of the list element.
++ *
++ * \note Only removal of the current element, \p pos, is safe. Removing
++ *       any other element during traversal may lead to a loop malfunction.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param tmp Temporary pointer of the same type as \p pos
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_safe(pos, tmp, head, member)                 \
++      for (pos = wl_container_of((head)->next, pos, member),          \
++           tmp = wl_container_of((pos)->member.next, tmp, member);    \
++           &pos->member != (head);                                    \
++           pos = tmp,                                                 \
++           tmp = wl_container_of(pos->member.next, tmp, member))
++
++/**
++ * Iterates backwards over a list.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_reverse(pos, head, member)                   \
++      for (pos = wl_container_of((head)->prev, pos, member);  \
++           &pos->member != (head);                                    \
++           pos = wl_container_of(pos->member.prev, pos, member))
++
++/**
++ * Iterates backwards over a list, safe against removal of the list element.
++ *
++ * \note Only removal of the current element, \p pos, is safe. Removing
++ *       any other element during traversal may lead to a loop malfunction.
++ *
++ * \sa wl_list_for_each()
++ *
++ * \param pos Cursor that each list element will be assigned to
++ * \param tmp Temporary pointer of the same type as \p pos
++ * \param head Head of the list to iterate over
++ * \param member Name of the link member within the element struct
++ *
++ * \relates wl_list
++ */
++#define wl_list_for_each_reverse_safe(pos, tmp, head, member)         \
++      for (pos = wl_container_of((head)->prev, pos, member),  \
++           tmp = wl_container_of((pos)->member.prev, tmp, member);    \
++           &pos->member != (head);                                    \
++           pos = tmp,                                                 \
++           tmp = wl_container_of(pos->member.prev, tmp, member))
++
++/**
++ * \class wl_array
++ *
++ * Dynamic array
++ *
++ * A wl_array is a dynamic array that can only grow until released. It is
++ * intended for relatively small allocations whose size is variable or not known
++ * in advance. While construction of a wl_array does not require all elements to
++ * be of the same size, wl_array_for_each() does require all elements to have
++ * the same type and size.
++ *
++ */
++struct wl_array {
++      /** Array size */
++      size_t size;
++      /** Allocated space */
++      size_t alloc;
++      /** Array data */
++      void *data;
++};
++
++/**
++ * Initializes the array.
++ *
++ * \param array Array to initialize
++ *
++ * \memberof wl_array
++ */
++void
++wl_array_init(struct wl_array *array);
++
++/**
++ * Releases the array data.
++ *
++ * \note Leaves the array in an invalid state.
++ *
++ * \param array Array whose data is to be released
++ *
++ * \memberof wl_array
++ */
++void
++wl_array_release(struct wl_array *array);
++
++/**
++ * Increases the size of the array by \p size bytes.
++ *
++ * \param array Array whose size is to be increased
++ * \param size Number of bytes to increase the size of the array by
++ *
++ * \return A pointer to the beginning of the newly appended space, or NULL when
++ *         resizing fails.
++ *
++ * \memberof wl_array
++ */
++void *
++wl_array_add(struct wl_array *array, size_t size);
++
++/**
++ * Copies the contents of \p source to \p array.
++ *
++ * \param array Destination array to copy to
++ * \param source Source array to copy from
++ *
++ * \return 0 on success, or -1 on failure
++ *
++ * \memberof wl_array
++ */
++int
++wl_array_copy(struct wl_array *array, struct wl_array *source);
++
++/**
++ * Iterates over an array.
++ *
++ * This macro expresses a for-each iterator for wl_array. It assigns each
++ * element in the array to \p pos, which can then be referenced in a trailing
++ * code block. \p pos must be a pointer to the array element type, and all
++ * array elements must be of the same type and size.
++ *
++ * \param pos Cursor that each array element will be assigned to
++ * \param array Array to iterate over
++ *
++ * \relates wl_array
++ * \sa wl_list_for_each()
++ */
++#define wl_array_for_each(pos, array)                                 \
++      for (pos = (array)->data;                                       \
++           (const char *) pos < ((const char *) (array)->data + (array)->size); \
++           (pos)++)
++
++/**
++ * Fixed-point number
++ *
++ * A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits
++ * of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t`
++ * as an opaque struct with methods that facilitate conversion to and from
++ * `double` and `int` types.
++ */
++typedef int32_t wl_fixed_t;
++
++/**
++ * Converts a fixed-point number to a floating-point number.
++ *
++ * \param f Fixed-point number to convert
++ *
++ * \return Floating-point representation of the fixed-point argument
++ */
++static inline double
++wl_fixed_to_double(wl_fixed_t f)
++{
++      union {
++              double d;
++              int64_t i;
++      } u;
++
++      u.i = ((1023LL + 44LL) << 52) + (1LL << 51) + f;
++
++      return u.d - (3LL << 43);
++}
++
++/**
++ * Converts a floating-point number to a fixed-point number.
++ *
++ * \param d Floating-point number to convert
++ *
++ * \return Fixed-point representation of the floating-point argument
++ */
++static inline wl_fixed_t
++wl_fixed_from_double(double d)
++{
++      union {
++              double d;
++              int64_t i;
++      } u;
++
++      u.d = d + (3LL << (51 - 8));
++
++      return (wl_fixed_t)u.i;
++}
++
++/**
++ * Converts a fixed-point number to an integer.
++ *
++ * \param f Fixed-point number to convert
++ *
++ * \return Integer component of the fixed-point argument
++ */
++static inline int
++wl_fixed_to_int(wl_fixed_t f)
++{
++      return f / 256;
++}
++
++/**
++ * Converts an integer to a fixed-point number.
++ *
++ * \param i Integer to convert
++ *
++ * \return Fixed-point representation of the integer argument
++ */
++static inline wl_fixed_t
++wl_fixed_from_int(int i)
++{
++      return i * 256;
++}
++
++/**
++ * Protocol message argument data types
++ *
++ * This union represents all of the argument types in the Wayland protocol wire
++ * format. The protocol implementation uses wl_argument within its marshalling
++ * machinery for dispatching messages between a client and a compositor.
++ *
++ * \sa wl_message
++ * \sa wl_interface
++ * \sa <a href="https://wayland.freedesktop.org/docs/html/ch04.html#sect-Protocol-wire-Format">Wire Format</a>
++ */
++union wl_argument {
++      int32_t i;           /**< `int`    */
++      uint32_t u;          /**< `uint`   */
++      wl_fixed_t f;        /**< `fixed`  */
++      const char *s;       /**< `string` */
++      struct wl_object *o; /**< `object` */
++      uint32_t n;          /**< `new_id` */
++      struct wl_array *a;  /**< `array`  */
++      int32_t h;           /**< `fd`     */
++};
++
++/**
++ * Dispatcher function type alias
++ *
++ * A dispatcher is a function that handles the emitting of callbacks in client
++ * code. For programs directly using the C library, this is done by using
++ * libffi to call function pointers. When binding to languages other than C,
++ * dispatchers provide a way to abstract the function calling process to be
++ * friendlier to other function calling systems.
++ *
++ * A dispatcher takes five arguments: The first is the dispatcher-specific
++ * implementation associated with the target object. The second is the object
++ * upon which the callback is being invoked (either wl_proxy or wl_resource).
++ * The third and fourth arguments are the opcode and the wl_message
++ * corresponding to the callback. The final argument is an array of arguments
++ * received from the other process via the wire protocol.
++ *
++ * \param "const void *" Dispatcher-specific implementation data
++ * \param "void *" Callback invocation target (wl_proxy or `wl_resource`)
++ * \param uint32_t Callback opcode
++ * \param "const struct wl_message *" Callback message signature
++ * \param "union wl_argument *" Array of received arguments
++ *
++ * \return 0 on success, or -1 on failure
++ */
++typedef int (*wl_dispatcher_func_t)(const void *, void *, uint32_t,
++                                  const struct wl_message *,
++                                  union wl_argument *);
++
++/**
++ * Log function type alias
++ *
++ * The C implementation of the Wayland protocol abstracts the details of
++ * logging. Users may customize the logging behavior, with a function conforming
++ * to the `wl_log_func_t` type, via `wl_log_set_handler_client` and
++ * `wl_log_set_handler_server`.
++ *
++ * A `wl_log_func_t` must conform to the expectations of `vprintf`, and
++ * expects two arguments: a string to write and a corresponding variable
++ * argument list. While the string to write may contain format specifiers and
++ * use values in the variable argument list, the behavior of any `wl_log_func_t`
++ * depends on the implementation.
++ *
++ * \note Take care to not confuse this with `wl_protocol_logger_func_t`, which
++ *       is a specific server-side logger for requests and events.
++ *
++ * \param "const char *" String to write to the log, containing optional format
++ *                       specifiers
++ * \param "va_list" Variable argument list
++ *
++ * \sa wl_log_set_handler_client
++ * \sa wl_log_set_handler_server
++ */
++typedef void (*wl_log_func_t)(const char *, va_list) WL_PRINTF(1, 0);
++
++/**
++ * Return value of an iterator function
++ *
++ * \sa wl_client_for_each_resource_iterator_func_t
++ * \sa wl_client_for_each_resource
++ */
++enum wl_iterator_result {
++      /** Stop the iteration */
++      WL_ITERATOR_STOP,
++      /** Continue the iteration */
++      WL_ITERATOR_CONTINUE
++};
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c5d786e25b951a18ed77e80de505543110e9b761
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,34 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#ifndef WAYLAND_VERSION_H
++#define WAYLAND_VERSION_H
++
++#define WAYLAND_VERSION_MAJOR @WAYLAND_VERSION_MAJOR@
++#define WAYLAND_VERSION_MINOR @WAYLAND_VERSION_MINOR@
++#define WAYLAND_VERSION_MICRO @WAYLAND_VERSION_MICRO@
++#define WAYLAND_VERSION "@WAYLAND_VERSION@"
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..78dfbb0a80b2f49f26cd4346c503cdfa3dd6ef07
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,157 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <string.h>
++#include "wayland-util.h"
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(array_init)
++{
++      struct wl_array array;
++
++      /* fill with garbage to emulate uninitialized memory */
++      memset(&array, 0x57, sizeof array);
++
++      wl_array_init(&array);
++      assert(array.size == 0);
++      assert(array.alloc == 0);
++      assert(array.data == 0);
++}
++
++TEST(array_release)
++{
++      struct wl_array array;
++      void *ptr;
++
++      wl_array_init(&array);
++      ptr = wl_array_add(&array, 1);
++      assert(ptr != NULL);
++      assert(array.data != NULL);
++
++      wl_array_release(&array);
++      assert(array.data == WL_ARRAY_POISON_PTR);
++}
++
++TEST(array_add)
++{
++      struct mydata {
++              unsigned int a;
++              unsigned int b;
++              double c;
++              double d;
++      };
++
++      const unsigned int iterations = 1321; /* this is arbitrary */
++      const int datasize = sizeof(struct mydata);
++      struct wl_array array;
++      size_t i;
++
++      wl_array_init(&array);
++
++      /* add some data */
++      for (i = 0; i < iterations; i++) {
++              struct mydata* ptr = wl_array_add(&array, datasize);
++              assert(ptr);
++              assert((i + 1) * datasize == array.size);
++
++              ptr->a = i * 3;
++              ptr->b = 20000 - i;
++              ptr->c = (double)(i);
++              ptr->d = (double)(i / 2.);
++      }
++
++      /* verify the data */
++      for (i = 0; i < iterations; ++i) {
++              struct mydata* check = (struct mydata*)array.data + i;
++
++              assert(check->a == i * 3);
++              assert(check->b == 20000 - i);
++              assert(check->c == (double)(i));
++              assert(check->d == (double)(i/2.));
++      }
++
++      wl_array_release(&array);
++}
++
++TEST(array_copy)
++{
++      const int iterations = 1529; /* this is arbitrary */
++      struct wl_array source;
++      struct wl_array copy;
++      int i;
++
++      wl_array_init(&source);
++
++      /* add some data */
++      for (i = 0; i < iterations; i++) {
++              int *p = wl_array_add(&source, sizeof(int));
++              assert(p);
++              *p = i * 2 + i;
++      }
++
++      /* copy the array */
++      wl_array_init(&copy);
++      wl_array_copy(&copy, &source);
++
++      /* check the copy */
++      for (i = 0; i < iterations; i++) {
++              int *s = (int *)source.data + i;
++              int *c = (int *)copy.data + i;
++
++              assert(*s == *c); /* verify the values are the same */
++              assert(s != c); /* ensure the addresses aren't the same */
++              assert(*s == i * 2 + i); /* sanity check */
++      }
++
++      wl_array_release(&source);
++      wl_array_release(&copy);
++}
++
++TEST(array_for_each)
++{
++      static const int elements[] = { 77, 12, 45192, 53280, 334455 };
++      struct wl_array array;
++      int *p;
++      int i;
++
++      wl_array_init(&array);
++      for (i = 0; i < 5; i++) {
++              p = wl_array_add(&array, sizeof *p);
++              assert(p);
++              *p = elements[i];
++      }
++
++      i = 0;
++      wl_array_for_each(p, &array) {
++              assert(*p == elements[i]);
++              i++;
++      }
++      assert(i == 5);
++
++      wl_array_release(&array);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..960cfa95978f2553149eb2b8147bde226b3c6169
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,91 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++struct client_destroy_listener {
++      struct wl_listener listener;
++      int done;
++};
++
++static void
++client_destroy_notify(struct wl_listener *l, void *data)
++{
++      struct client_destroy_listener *listener =
++              wl_container_of(l, listener, listener);
++
++      listener->done = 1;
++}
++
++TEST(client_destroy_listener)
++{
++      struct wl_display *display;
++      struct wl_client *client;
++      struct client_destroy_listener a, b;
++      int s[2];
++
++      assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++      display = wl_display_create();
++      assert(display);
++      client = wl_client_create(display, s[0]);
++      assert(client);
++
++      a.listener.notify = client_destroy_notify;
++      a.done = 0;
++      wl_client_add_destroy_listener(client, &a.listener);
++
++      assert(wl_client_get_destroy_listener(client, client_destroy_notify) ==
++             &a.listener);
++
++      b.listener.notify = client_destroy_notify;
++      b.done = 0;
++      wl_client_add_destroy_listener(client, &b.listener);
++
++      wl_list_remove(&a.listener.link);
++
++      wl_client_destroy(client);
++
++      assert(!a.done);
++      assert(b.done);
++
++      close(s[0]);
++      close(s[1]);
++
++      wl_display_destroy(display);
++}
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..064d25307152a804c98eee49106ad7eac1b8f16d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,172 @@@
++/*
++ * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++      char *val = getenv("XDG_RUNTIME_DIR");
++      assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++      return val;
++}
++
++struct compositor {
++      struct wl_display *display;
++      struct wl_listener listener;
++      struct wl_client *client;
++};
++
++static void
++client_created(struct wl_listener *listener, void *data)
++{
++      struct compositor *c = wl_container_of(listener, c, listener);
++      c->client = data;
++}
++
++static void
++check_client_list(struct compositor *compositor)
++{
++      struct wl_list *client_list;
++      struct wl_client *client, *client_it;
++      int num_clients = 0;
++
++      client_list = wl_display_get_client_list(compositor->display);
++      wl_client_for_each(client_it, client_list) {
++              num_clients++;
++              client = client_it;
++      }
++      assert(num_clients == 1);
++      /* 'client_it' is not valid here, so we took a copy of the client in the loop.
++       * We could also do this assert in the loop directly, but in case it fails it is
++       * easier to understand the problem when we know that the previous assert passed,
++       * so that there is only one client but the wrong one. */
++      assert(compositor->client == client);
++}
++
++static const char *
++setup_compositor(struct compositor *compositor)
++{
++      const char *socket;
++
++      require_xdg_runtime_dir();
++
++      compositor->display = wl_display_create();
++      socket = wl_display_add_socket_auto(compositor->display);
++
++      compositor->listener.notify = client_created;
++      wl_display_add_client_created_listener(compositor->display, &compositor->listener);
++
++      return socket;
++}
++
++static void
++cleanup_compositor(struct compositor *compositor)
++{
++      wl_client_destroy(compositor->client);
++      wl_display_destroy(compositor->display);
++}
++
++TEST(new_client_connect)
++{
++      const char *socket;
++      struct compositor compositor = { 0 };
++      struct {
++              struct wl_display *display;
++      } client;
++
++      socket = setup_compositor(&compositor);
++
++      client.display = wl_display_connect(socket);
++
++      wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++      assert(compositor.client != NULL);
++
++      check_client_list(&compositor);
++
++
++
++      wl_display_disconnect(client.display);
++      cleanup_compositor(&compositor);
++}
++
++struct resource_listener {
++      struct wl_listener listener;
++      int count;
++};
++
++static void
++resource_created(struct wl_listener *listener, void *data)
++{
++      struct resource_listener *l;
++      l = wl_container_of(listener, l, listener);
++      l->count++;
++}
++
++TEST(new_resource)
++{
++      const char *socket;
++      struct compositor compositor = { 0 };
++      struct {
++              struct wl_display *display;
++              struct wl_callback *cb;
++      } client;
++      struct resource_listener resource_listener;
++
++      socket = setup_compositor(&compositor);
++      client.display = wl_display_connect(socket);
++      wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++      resource_listener.count = 0;
++      resource_listener.listener.notify = resource_created;
++      wl_client_add_resource_created_listener(compositor.client,
++                                              &resource_listener.listener);
++
++      client.cb = wl_display_sync(client.display);
++      wl_display_flush(client.display);
++      wl_event_loop_dispatch(wl_display_get_event_loop(compositor.display), 100);
++
++      assert(resource_listener.count == 1);
++
++      wl_callback_destroy(client.cb);
++      wl_display_disconnect(client.display);
++      cleanup_compositor(&compositor);
++
++      /* This is defined to be safe also after client destruction */
++      wl_list_remove(&resource_listener.listener.link);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9762e0da2033834d1b71baf7285b7460be33d64e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,848 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <math.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <poll.h>
++
++#include "wayland-private.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++static const char message[] = "Hello, world";
++
++static struct wl_connection *
++setup(int *s)
++{
++      struct wl_connection *connection;
++
++      assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++
++      connection = wl_connection_create(s[0]);
++      assert(connection);
++
++      return connection;
++}
++
++TEST(connection_create)
++{
++      struct wl_connection *connection;
++      int s[2];
++
++      connection = setup(s);
++      wl_connection_destroy(connection);
++      close(s[0]);
++      close(s[1]);
++}
++
++TEST(connection_write)
++{
++      struct wl_connection *connection;
++      int s[2];
++      char buffer[64];
++
++      connection = setup(s);
++
++      assert(wl_connection_write(connection, message, sizeof message) == 0);
++      assert(wl_connection_flush(connection) == sizeof message);
++      assert(read(s[1], buffer, sizeof buffer) == sizeof message);
++      assert(memcmp(message, buffer, sizeof message) == 0);
++
++      wl_connection_destroy(connection);
++      close(s[0]);
++      close(s[1]);
++}
++
++TEST(connection_data)
++{
++      struct wl_connection *connection;
++      int s[2];
++      char buffer[64];
++
++      connection = setup(s);
++
++      assert(write(s[1], message, sizeof message) == sizeof message);
++      assert(wl_connection_read(connection) == sizeof message);
++      wl_connection_copy(connection, buffer, sizeof message);
++      assert(memcmp(message, buffer, sizeof message) == 0);
++      wl_connection_consume(connection, sizeof message);
++
++      wl_connection_destroy(connection);
++      close(s[0]);
++      close(s[1]);
++}
++
++TEST(connection_queue)
++{
++      struct wl_connection *connection;
++      int s[2];
++      char buffer[64];
++
++      connection = setup(s);
++
++      /* Test that wl_connection_queue() puts data in the output
++       * buffer without flush it.  Verify that the data did get in
++       * the buffer by writing another message and making sure that
++       * we receive the two messages on the other fd. */
++
++      assert(wl_connection_queue(connection, message, sizeof message) == 0);
++      assert(wl_connection_flush(connection) == 0);
++      assert(wl_connection_write(connection, message, sizeof message) == 0);
++      assert(wl_connection_flush(connection) == 2 * sizeof message);
++      assert(read(s[1], buffer, sizeof buffer) == 2 * sizeof message);
++      assert(memcmp(message, buffer, sizeof message) == 0);
++      assert(memcmp(message, buffer + sizeof message, sizeof message) == 0);
++
++      wl_connection_destroy(connection);
++      close(s[0]);
++      close(s[1]);
++}
++
++static void
++va_list_wrapper(const char *signature, union wl_argument *args, int count, ...)
++{
++      va_list ap;
++      va_start(ap, count);
++      wl_argument_from_va_list(signature, args, count, ap);
++      va_end(ap);
++}
++
++TEST(argument_from_va_list)
++{
++      union wl_argument args[WL_CLOSURE_MAX_ARGS];
++      struct wl_object fake_object, fake_new_object;
++      struct wl_array fake_array;
++
++      va_list_wrapper("i", args, 1, 100);
++      assert(args[0].i == 100);
++
++      va_list_wrapper("is", args, 2, 101, "value");
++      assert(args[0].i == 101);
++      assert(strcmp(args[1].s, "value") == 0);
++
++      va_list_wrapper("?iuf?sonah", args, 8,
++                      102, 103, wl_fixed_from_int(104), "value",
++                      &fake_object, &fake_new_object, &fake_array, 106);
++      assert(args[0].i == 102);
++      assert(args[1].u == 103);
++      assert(args[2].f == wl_fixed_from_int(104));
++      assert(strcmp(args[3].s, "value") == 0);
++      assert(args[4].o == &fake_object);
++      assert(args[5].o == &fake_new_object);
++      assert(args[6].a == &fake_array);
++      assert(args[7].h == 106);
++}
++
++struct marshal_data {
++      struct wl_connection *read_connection;
++      struct wl_connection *write_connection;
++      int s[2];
++      uint32_t buffer[10];
++      union {
++              uint32_t u;
++              int32_t i;
++              const char *s;
++              int h;
++      } value;
++};
++
++static void
++setup_marshal_data(struct marshal_data *data)
++{
++      assert(socketpair(AF_UNIX,
++                        SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
++      data->read_connection = wl_connection_create(data->s[0]);
++      assert(data->read_connection);
++      data->write_connection = wl_connection_create(data->s[1]);
++      assert(data->write_connection);
++}
++
++static void
++release_marshal_data(struct marshal_data *data)
++{
++      close(wl_connection_destroy(data->read_connection));
++      close(wl_connection_destroy(data->write_connection));
++}
++
++static void
++marshal(struct marshal_data *data, const char *format, int size, ...)
++{
++      struct wl_closure *closure;
++      static const uint32_t opcode = 4444;
++      static struct wl_object sender = { NULL, NULL, 1234 };
++      struct wl_message message = { "test", format, NULL };
++      va_list ap;
++
++      va_start(ap, size);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure);
++      assert(wl_closure_send(closure, data->write_connection) == 0);
++      wl_closure_destroy(closure);
++      assert(wl_connection_flush(data->write_connection) == size);
++      assert(read(data->s[0], data->buffer, sizeof data->buffer) == size);
++
++      assert(data->buffer[0] == sender.id);
++      assert(data->buffer[1] == (opcode | (size << 16)));
++}
++
++TEST(connection_marshal)
++{
++      struct marshal_data data;
++      struct wl_object object;
++      struct wl_array array;
++      static const char text[] = "curry";
++
++      setup_marshal_data(&data);
++
++      marshal(&data, "i", 12, 42);
++      assert(data.buffer[2] == 42);
++
++      marshal(&data, "u", 12, 55);
++      assert(data.buffer[2] == 55);
++
++      marshal(&data, "s", 20, "frappo");
++      assert(data.buffer[2] == 7);
++      assert(strcmp((char *) &data.buffer[3], "frappo") == 0);
++
++      object.id = 557799;
++      marshal(&data, "o", 12, &object);
++      assert(data.buffer[2] == object.id);
++
++      marshal(&data, "n", 12, &object);
++      assert(data.buffer[2] == object.id);
++
++      array.data = (void *) text;
++      array.size = sizeof text;
++      marshal(&data, "a", 20, &array);
++      assert(data.buffer[2] == array.size);
++      assert(memcmp(&data.buffer[3], text, array.size) == 0);
++
++      release_marshal_data(&data);
++}
++
++static void
++expected_fail_marshal(int expected_error, const char *format, ...)
++{
++      struct wl_closure *closure;
++      static const uint32_t opcode = 4444;
++      static const struct wl_interface test_interface = {
++              .name = "test_object"
++      };
++      static struct wl_object sender = { 0 };
++      struct wl_message message = { "test", format, NULL };
++
++      sender.interface = &test_interface;
++      sender.id = 1234;
++      va_list ap;
++
++      va_start(ap, format);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure == NULL);
++      assert(errno == expected_error);
++}
++
++static void
++expected_fail_marshal_send(struct marshal_data *data, int expected_error,
++                         const char *format, ...)
++{
++      struct wl_closure *closure;
++      static const uint32_t opcode = 4444;
++      static struct wl_object sender = { NULL, NULL, 1234 };
++      struct wl_message message = { "test", format, NULL };
++      va_list ap;
++
++      va_start(ap, format);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure);
++      assert(wl_closure_send(closure, data->write_connection) < 0);
++      assert(errno == expected_error);
++
++      wl_closure_destroy(closure);
++}
++
++TEST(connection_marshal_nullables)
++{
++      struct marshal_data data;
++      struct wl_object object;
++      const char text[] = "curry";
++
++      setup_marshal_data(&data);
++
++      expected_fail_marshal(EINVAL, "o", NULL);
++      expected_fail_marshal(EINVAL, "s", NULL);
++      expected_fail_marshal(EINVAL, "a", NULL);
++
++      marshal(&data, "?o", 12, NULL);
++      assert(data.buffer[2] == 0);
++
++      marshal(&data, "?s", 12, NULL);
++      assert(data.buffer[2] == 0);
++
++      object.id = 55293;
++      marshal(&data, "?o", 12, &object);
++      assert(data.buffer[2] == object.id);
++
++      marshal(&data, "?s", 20, text);
++      assert(data.buffer[2] == sizeof text);
++      assert(strcmp((char *) &data.buffer[3], text) == 0);
++
++      release_marshal_data(&data);
++}
++
++static void
++validate_demarshal_u(struct marshal_data *data,
++                   struct wl_object *object, uint32_t u)
++{
++      assert(data->value.u == u);
++}
++
++static void
++validate_demarshal_i(struct marshal_data *data,
++                   struct wl_object *object, int32_t i)
++{
++      assert(data->value.i == i);
++}
++
++static void
++validate_demarshal_s(struct marshal_data *data,
++                   struct wl_object *object, const char *s)
++{
++      if (data->value.s != NULL)
++              assert(strcmp(data->value.s, s) == 0);
++      else
++              assert(s == NULL);
++}
++
++static void
++validate_demarshal_h(struct marshal_data *data,
++                   struct wl_object *object, int fd)
++{
++      struct stat buf1, buf2;
++
++      assert(fd != data->value.h);
++      fstat(fd, &buf1);
++      fstat(data->value.h, &buf2);
++      assert(buf1.st_dev == buf2.st_dev);
++      assert(buf1.st_ino == buf2.st_ino);
++      close(fd);
++      close(data->value.h);
++}
++
++static void
++validate_demarshal_f(struct marshal_data *data,
++                   struct wl_object *object, wl_fixed_t f)
++{
++      assert(data->value.i == f);
++}
++
++static void
++demarshal(struct marshal_data *data, const char *format,
++        uint32_t *msg, void (*func)(void))
++{
++      struct wl_message message = { "test", format, NULL };
++      struct wl_closure *closure;
++      struct wl_map objects;
++      struct wl_object object = { NULL, &func, 0 };
++      int size = msg[1] >> 16;
++
++      assert(write(data->s[1], msg, size) == size);
++      assert(wl_connection_read(data->read_connection) == size);
++
++      wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++      object.id = msg[0];
++      closure = wl_connection_demarshal(data->read_connection,
++                                        size, &objects, &message);
++      assert(closure);
++      wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++      wl_closure_destroy(closure);
++}
++
++TEST(connection_demarshal)
++{
++      struct marshal_data data;
++      uint32_t msg[10];
++
++      setup_marshal_data(&data);
++
++      data.value.u = 8000;
++      msg[0] = 400200;        /* object id */
++      msg[1] = 12 << 16;              /* size = 12, opcode = 0 */
++      msg[2] = data.value.u;
++      demarshal(&data, "u", msg, (void *) validate_demarshal_u);
++
++      data.value.i = -557799;
++      msg[0] = 400200;
++      msg[1] = 12 << 16;
++      msg[2] = data.value.i;
++      demarshal(&data, "i", msg, (void *) validate_demarshal_i);
++
++      data.value.s = "superdude";
++      msg[0] = 400200;
++      msg[1] = 24 << 16;
++      msg[2] = 10;
++      msg[3 + msg[2]/4] = 0;
++      memcpy(&msg[3], data.value.s, msg[2]);
++      demarshal(&data, "s", msg, (void *) validate_demarshal_s);
++
++      data.value.s = "superdude";
++      msg[0] = 400200;
++      msg[1] = 24 << 16;
++      msg[2] = 10;
++      msg[3 + msg[2]/4] = 0;
++      memcpy(&msg[3], data.value.s, msg[2]);
++      demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++      data.value.i = wl_fixed_from_double(-90000.2390);
++      msg[0] = 400200;
++      msg[1] = 12 << 16;
++      msg[2] = data.value.i;
++      demarshal(&data, "f", msg, (void *) validate_demarshal_f);
++
++      data.value.s = NULL;
++      msg[0] = 400200;
++      msg[1] = 12 << 16;
++      msg[2] = 0;
++      demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++      release_marshal_data(&data);
++}
++
++static void
++marshal_demarshal(struct marshal_data *data,
++                void (*func)(void), int size, const char *format, ...)
++{
++      struct wl_closure *closure;
++      static const int opcode = 4444;
++      static struct wl_object sender = { NULL, NULL, 1234 };
++      struct wl_message message = { "test", format, NULL };
++      struct wl_map objects;
++      struct wl_object object = { NULL, &func, 0 };
++      va_list ap;
++      uint32_t msg[1] = { 1234 };
++
++      va_start(ap, format);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure);
++      assert(wl_closure_send(closure, data->write_connection) == 0);
++      wl_closure_destroy(closure);
++      assert(wl_connection_flush(data->write_connection) == size);
++
++      assert(wl_connection_read(data->read_connection) == size);
++
++      wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++      object.id = msg[0];
++      closure = wl_connection_demarshal(data->read_connection,
++                                        size, &objects, &message);
++      assert(closure);
++      wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++      wl_closure_destroy(closure);
++}
++
++TEST(connection_marshal_demarshal)
++{
++      struct marshal_data data;
++      char f[] = "/tmp/wayland-tests-XXXXXX";
++
++      setup_marshal_data(&data);
++
++      data.value.u = 889911;
++      marshal_demarshal(&data, (void *) validate_demarshal_u,
++                        12, "u", data.value.u);
++
++      data.value.i = -13;
++      marshal_demarshal(&data, (void *) validate_demarshal_i,
++                        12, "i", data.value.i);
++
++      data.value.s = "cookie robots";
++      marshal_demarshal(&data, (void *) validate_demarshal_s,
++                        28, "s", data.value.s);
++
++      data.value.s = "cookie robots";
++      marshal_demarshal(&data, (void *) validate_demarshal_s,
++                        28, "?s", data.value.s);
++
++      data.value.h = mkstemp(f);
++      assert(data.value.h >= 0);
++      unlink(f);
++      marshal_demarshal(&data, (void *) validate_demarshal_h,
++                        8, "h", data.value.h);
++
++      data.value.i = wl_fixed_from_double(1234.5678);
++      marshal_demarshal(&data, (void *) validate_demarshal_f,
++                        12, "f", data.value.i);
++
++      data.value.i = wl_fixed_from_double(-90000.2390);
++      marshal_demarshal(&data, (void *) validate_demarshal_f,
++                        12, "f", data.value.i);
++
++      data.value.i = wl_fixed_from_double((1 << 23) - 1 + 0.0941);
++      marshal_demarshal(&data, (void *) validate_demarshal_f,
++                        12, "f", data.value.i);
++
++      release_marshal_data(&data);
++}
++
++static void
++expected_fail_demarshal(struct marshal_data *data, const char *format,
++                        const uint32_t *msg, int expected_error)
++{
++      struct wl_message message = { "test", format, NULL };
++      struct wl_closure *closure;
++      struct wl_map objects;
++      int size = (msg[1] >> 16);
++
++      assert(write(data->s[1], msg, size) == size);
++      assert(wl_connection_read(data->read_connection) == size);
++
++      wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++      closure = wl_connection_demarshal(data->read_connection,
++                                          size, &objects, &message);
++
++      assert(closure == NULL);
++      assert(errno == expected_error);
++}
++
++TEST(connection_demarshal_null_strings)
++{
++      struct marshal_data data;
++      uint32_t msg[3];
++
++      setup_marshal_data(&data);
++
++      data.value.s = NULL;
++      msg[0] = 400200;        /* object id */
++      msg[1] = 12 << 16;      /* size = 12, opcode = 0 */
++      msg[2] = 0;             /* string length = 0 */
++      demarshal(&data, "?s", msg, (void *) validate_demarshal_s);
++
++      expected_fail_demarshal(&data, "s", msg, EINVAL);
++
++      release_marshal_data(&data);
++}
++
++/* These tests are verifying that the demarshaling code will gracefully handle
++ * clients lying about string and array lengths and giving values near
++ * UINT32_MAX. Before fixes f7fdface and f5b9e3b9 this test would crash on
++ * 32bit systems.
++ */
++TEST(connection_demarshal_failures)
++{
++      struct marshal_data data;
++      unsigned int i;
++      uint32_t msg[3];
++
++      const uint32_t overflowing_values[] = {
++              /* Values very close to UINT32_MAX. Before f5b9e3b9 these
++               * would cause integer overflow in DIV_ROUNDUP. */
++              0xffffffff, 0xfffffffe, 0xfffffffd, 0xfffffffc,
++
++              /* Values at various offsets from UINT32_MAX. Before f7fdface
++               * these would overflow the "p" pointer on 32bit systems,
++               * effectively subtracting the offset from it. It had good
++               * chance to cause crash depending on what was stored at that
++               * offset before "p". */
++              0xfffff000, 0xffffd000, 0xffffc000, 0xffffb000
++      };
++
++      setup_marshal_data(&data);
++
++      /* sender_id, does not matter */
++      msg[0] = 0;
++
++      /* (size << 16 | opcode), opcode is 0, does not matter */
++      msg[1] = sizeof(msg) << 16;
++
++      for (i = 0; i < ARRAY_LENGTH(overflowing_values); i++) {
++              /* length of the string or array */
++              msg[2] = overflowing_values[i];
++
++              expected_fail_demarshal(&data, "s", msg, EINVAL);
++              expected_fail_demarshal(&data, "a", msg, EINVAL);
++      }
++
++      release_marshal_data(&data);
++}
++
++TEST(connection_marshal_alot)
++{
++      struct marshal_data data;
++      char f[64];
++      int i;
++
++      setup_marshal_data(&data);
++
++      /* We iterate enough to make sure we wrap the circular buffers
++       * for both regular data an fds. */
++
++      for (i = 0; i < 2000; i++) {
++              strcpy(f, "/tmp/wayland-tests-XXXXXX");
++              data.value.h = mkstemp(f);
++              assert(data.value.h >= 0);
++              unlink(f);
++              marshal_demarshal(&data, (void *) validate_demarshal_h,
++                                8, "h", data.value.h);
++      }
++
++      release_marshal_data(&data);
++}
++
++TEST(connection_marshal_too_big)
++{
++      struct marshal_data data;
++      char *big_string = malloc(5000);
++
++      assert(big_string);
++
++      memset(big_string, ' ', 4999);
++      big_string[4999] = '\0';
++
++      setup_marshal_data(&data);
++
++      expected_fail_marshal_send(&data, E2BIG, "s", big_string);
++
++      release_marshal_data(&data);
++      free(big_string);
++}
++
++static void
++marshal_helper(const char *format, void *handler, ...)
++{
++      struct wl_closure *closure;
++      static struct wl_object sender = { NULL, NULL, 1234 };
++      struct wl_object object = { NULL, &handler, 0 };
++      static const int opcode = 4444;
++      struct wl_message message = { "test", format, NULL };
++      va_list ap;
++      int done;
++
++      va_start(ap, handler);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure);
++      done = 0;
++      wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, &done);
++      wl_closure_destroy(closure);
++      assert(done);
++}
++
++static void
++suu_handler(void *data, struct wl_object *object,
++          const char *s, uint32_t u1, uint32_t u2)
++{
++      int *done = data;
++
++      assert(strcmp(s, "foo") == 0);
++      assert(u1 == 500);
++      assert(u2 == 404040);
++      *done = 1;
++}
++
++TEST(invoke_closure)
++{
++      marshal_helper("suu", suu_handler, "foo", 500, 404040);
++}
++
++static void
++leak_closure(void)
++{
++      struct wl_callback *cb;
++      struct pollfd pfd;
++      struct client *c = client_connect();
++
++      cb = wl_display_sync(c->wl_display);
++      assert(cb);
++      assert(wl_display_flush(c->wl_display) > 0);
++
++      /* we don't need it, it is referenced */
++      wl_callback_destroy(cb);
++
++      pfd.fd = wl_display_get_fd(c->wl_display);
++      pfd.events = POLLIN;
++
++      test_set_timeout(2);
++      assert(poll(&pfd, 1, -1) == 1);
++
++      /* read events, but do not dispatch them */
++      assert(wl_display_prepare_read(c->wl_display) == 0);
++      assert(wl_display_read_events(c->wl_display) == 0);
++
++      /*
++       * now we have wl_callback.done and wl_display.delete_id queued;
++       * if we now release the queue (in wl_display_disconnect())
++       * we should not leak memory
++       */
++
++      client_disconnect(c);
++}
++
++TEST(closure_leaks)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, leak_closure);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void
++leak_after_error(void)
++{
++      struct client *c = client_connect();
++
++      /* this should return -1, because we'll send error
++       * from server. */
++      assert(stop_display(c, 1) == -1);
++      assert(wl_display_dispatch_pending(c->wl_display) == -1);
++      assert(wl_display_get_error(c->wl_display) == ENOMEM);
++
++      /* after we got error, we have display_resume event
++       * in the queue. It should be freed in wl_display_disconnect().
++       * Let's see! */
++
++      wl_proxy_destroy((struct wl_proxy *) c->tc);
++      wl_display_disconnect(c->wl_display);
++      free(c);
++}
++
++TEST(closure_leaks_after_error)
++{
++      struct display *d = display_create();
++      struct client_info *cl;
++
++      cl = client_create_noarg(d, leak_after_error);
++      display_run(d);
++
++      wl_client_post_no_memory(cl->wl_client);
++      display_resume(d);
++
++      display_destroy(d);
++}
++
++/** Raw read from socket expecting wl_display.error
++ *
++ * \param sockfd The socket to read from.
++ * \param expected_error The expected wl_display error code.
++ *
++ * Reads the socket and manually parses one message, expecting it to be a
++ * wl_display.error with the wl_display as the originating object.
++ * Asserts that the received error code is expected_error.
++ */
++static void
++expect_error_recv(int sockfd, uint32_t expected_error)
++{
++      uint32_t buf[1024];
++      ssize_t slen;
++      uint32_t opcode;
++      int str_len;
++
++      slen = recv(sockfd, buf, sizeof buf, 0);
++      assert(slen >= 2 * (ssize_t)sizeof (uint32_t));
++      opcode = buf[1] & 0xffff;
++      fprintf(stderr, "Received %zd bytes, object %u, opcode %u\n",
++              slen, buf[0], opcode);
++
++      /* check error event */
++      assert(buf[0] == 1);
++      assert(opcode == WL_DISPLAY_ERROR);
++
++      str_len = buf[4];
++      assert(str_len > 0);
++      assert(str_len <= slen - 5 * (ssize_t)sizeof (uint32_t));
++      fprintf(stderr, "Error event on object %u, code %u, message \"%*s\"\n",
++              buf[2], buf[3], str_len, (const char *)&buf[5]);
++
++      assert(buf[3] == expected_error);
++}
++
++/* A test for https://gitlab.freedesktop.org/wayland/wayland/issues/52
++ * trying to provoke a read from uninitialized memory in
++ * wl_connection_demarshal() for sender_id and opcode.
++ *
++ * This test might not fail as is even with #52 unfixed, since there is no way
++ * to detect what happens and the crash with zero size depends on stack content.
++ * However, running under Valgrind would point out invalid reads and use of
++ * uninitialized values.
++ */
++TEST(request_bogus_size)
++{
++      struct wl_display *display;
++      struct wl_client *client;
++      int s[2];
++      uint32_t msg[3];
++      int bogus_size;
++
++      test_set_timeout(1);
++
++      /*
++       * The manufactured message has real size 12. Test all bogus sizes
++       * smaller than that, and zero as the last one since wl_closure_init
++       * handles zero specially and having garbage in the stack makes it more
++       * likely to crash in wl_connection_demarshal.
++       */
++      for (bogus_size = 11; bogus_size >= 0; bogus_size--) {
++              fprintf(stderr, "* bogus size %d\n", bogus_size);
++
++              assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++              display = wl_display_create();
++              assert(display);
++              client = wl_client_create(display, s[0]);
++              assert(client);
++
++              /* manufacture a request that lies about its size */
++              msg[0] = 1; /* sender id: wl_display */
++              msg[1] = (bogus_size << 16) | WL_DISPLAY_SYNC; /* size and opcode */
++              msg[2] = 2; /* sync argument: new_id for wl_callback */
++
++              assert(send(s[1], msg, sizeof msg, 0) == sizeof msg);
++
++              wl_event_loop_dispatch(wl_display_get_event_loop(display), 0);
++
++              expect_error_recv(s[1], WL_DISPLAY_ERROR_INVALID_METHOD);
++
++              /* Do not wl_client_destroy, the error already caused it. */
++              close(s[1]);
++              wl_display_destroy(display);
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1e84e6376e651ad1d89d3ffb95e4e5c61c996959
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5 @@@
++/* This source should compile fine with C++ compiler */
++#include "wayland-server-protocol.h"
++
++int main() { return 0; }
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..ac2a6b76b695d64553c84e91ee637868ecd914e9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="the_interface" version="1">
++    <description summary="the summary">
++    </description>
++    <request name="the_request">
++      <arg name="" type="uint"/>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..6ea2fae08a9ba632489ac89d22b020a213f04e88
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,11 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="the_interface" version="1">
++    <description summary="the summary">
++    </description>
++    <enum name="4the_enum">
++      <entry name="60_seconds" value="1" summary="this is the first"/>
++      <entry name="invalid entry" value="2" summary="this is the first"/>
++    </enum>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..3225384e5eca0ae6de23db0cf4ea0d3eb96145e4
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="the_interface" version="1">
++    <description summary="the summary">
++    </description>
++    <enum name="the-enum">
++      <entry name="the_entry" value="0" summary="entry summary"/>
++    </enum>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..9708e3bc54c1305a061532a75d05da26330704f6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="the_interface" version="1">
++    <description summary="the summary">
++    </description>
++    <event name="theΔevent"/>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..17404c5e4cbe8f4e6df2771190f68a87d597d269
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="inter face" version="1">
++    <description summary="the summary">
++    </description>
++    <event name="the_event"/>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7a172045115a16aa7954bdeaf7aae5716ea79495
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="1badprotocol">
++  <interface name="required_interface" version="13">
++    <description summary="required summary">
++    </description>
++    <event name="requied_event"/>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a68c8aac402ae0971c82cf0bef2f693d8ee5b878
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,10 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="the_protocol">
++  <interface name="the_interface" version="1">
++    <description summary="the summary">
++    </description>
++    <request name="req-west">
++      <arg name="the_arg" type="uint"/>
++    </request>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a14b5e0033689e13be68079265b83c701e578ca8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,5625 @@@
++/* SCANNER TEST */
++
++#ifndef WAYLAND_CLIENT_PROTOCOL_H
++#define WAYLAND_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_wayland The wayland protocol
++ * @section page_ifaces_wayland Interfaces
++ * - @subpage page_iface_wl_display - core global object
++ * - @subpage page_iface_wl_registry - global registry object
++ * - @subpage page_iface_wl_callback - callback object
++ * - @subpage page_iface_wl_compositor - the compositor singleton
++ * - @subpage page_iface_wl_shm_pool - a shared memory pool
++ * - @subpage page_iface_wl_shm - shared memory support
++ * - @subpage page_iface_wl_buffer - content for a wl_surface
++ * - @subpage page_iface_wl_data_offer - offer to transfer data
++ * - @subpage page_iface_wl_data_source - offer to transfer data
++ * - @subpage page_iface_wl_data_device - data transfer device
++ * - @subpage page_iface_wl_data_device_manager - data transfer interface
++ * - @subpage page_iface_wl_shell - create desktop-style surfaces
++ * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface
++ * - @subpage page_iface_wl_surface - an onscreen surface
++ * - @subpage page_iface_wl_seat - group of input devices
++ * - @subpage page_iface_wl_pointer - pointer input device
++ * - @subpage page_iface_wl_keyboard - keyboard input device
++ * - @subpage page_iface_wl_touch - touchscreen input device
++ * - @subpage page_iface_wl_output - compositor output region
++ * - @subpage page_iface_wl_region - region interface
++ * - @subpage page_iface_wl_subcompositor - sub-surface compositing
++ * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
++ * @section page_copyright_wayland Copyright
++ * <pre>
++ *
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct wl_buffer;
++struct wl_callback;
++struct wl_compositor;
++struct wl_data_device;
++struct wl_data_device_manager;
++struct wl_data_offer;
++struct wl_data_source;
++struct wl_display;
++struct wl_keyboard;
++struct wl_output;
++struct wl_pointer;
++struct wl_region;
++struct wl_registry;
++struct wl_seat;
++struct wl_shell;
++struct wl_shell_surface;
++struct wl_shm;
++struct wl_shm_pool;
++struct wl_subcompositor;
++struct wl_subsurface;
++struct wl_surface;
++struct wl_touch;
++
++#ifndef WL_DISPLAY_INTERFACE
++#define WL_DISPLAY_INTERFACE
++/**
++ * @page page_iface_wl_display wl_display
++ * @section page_iface_wl_display_desc Description
++ *
++ * The core global object.  This is a special singleton object.  It
++ * is used for internal Wayland protocol features.
++ * @section page_iface_wl_display_api API
++ * See @ref iface_wl_display.
++ */
++/**
++ * @defgroup iface_wl_display The wl_display interface
++ *
++ * The core global object.  This is a special singleton object.  It
++ * is used for internal Wayland protocol features.
++ */
++extern const struct wl_interface wl_display_interface;
++#endif
++#ifndef WL_REGISTRY_INTERFACE
++#define WL_REGISTRY_INTERFACE
++/**
++ * @page page_iface_wl_registry wl_registry
++ * @section page_iface_wl_registry_desc Description
++ *
++ * The singleton global registry object.  The server has a number of
++ * global objects that are available to all clients.  These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry.  Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes.  To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request.  This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ * @section page_iface_wl_registry_api API
++ * See @ref iface_wl_registry.
++ */
++/**
++ * @defgroup iface_wl_registry The wl_registry interface
++ *
++ * The singleton global registry object.  The server has a number of
++ * global objects that are available to all clients.  These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry.  Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes.  To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request.  This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ */
++extern const struct wl_interface wl_registry_interface;
++#endif
++#ifndef WL_CALLBACK_INTERFACE
++#define WL_CALLBACK_INTERFACE
++/**
++ * @page page_iface_wl_callback wl_callback
++ * @section page_iface_wl_callback_desc Description
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ * @section page_iface_wl_callback_api API
++ * See @ref iface_wl_callback.
++ */
++/**
++ * @defgroup iface_wl_callback The wl_callback interface
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ */
++extern const struct wl_interface wl_callback_interface;
++#endif
++#ifndef WL_COMPOSITOR_INTERFACE
++#define WL_COMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_compositor wl_compositor
++ * @section page_iface_wl_compositor_desc Description
++ *
++ * A compositor.  This object is a singleton global.  The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ * @section page_iface_wl_compositor_api API
++ * See @ref iface_wl_compositor.
++ */
++/**
++ * @defgroup iface_wl_compositor The wl_compositor interface
++ *
++ * A compositor.  This object is a singleton global.  The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ */
++extern const struct wl_interface wl_compositor_interface;
++#endif
++#ifndef WL_SHM_POOL_INTERFACE
++#define WL_SHM_POOL_INTERFACE
++/**
++ * @page page_iface_wl_shm_pool wl_shm_pool
++ * @section page_iface_wl_shm_pool_desc Description
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client.  Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ * @section page_iface_wl_shm_pool_api API
++ * See @ref iface_wl_shm_pool.
++ */
++/**
++ * @defgroup iface_wl_shm_pool The wl_shm_pool interface
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client.  Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ */
++extern const struct wl_interface wl_shm_pool_interface;
++#endif
++#ifndef WL_SHM_INTERFACE
++#define WL_SHM_INTERFACE
++/**
++ * @page page_iface_wl_shm wl_shm
++ * @section page_iface_wl_shm_desc Description
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ * @section page_iface_wl_shm_api API
++ * See @ref iface_wl_shm.
++ */
++/**
++ * @defgroup iface_wl_shm The wl_shm interface
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ */
++extern const struct wl_interface wl_shm_interface;
++#endif
++#ifndef WL_BUFFER_INTERFACE
++#define WL_BUFFER_INTERFACE
++/**
++ * @page page_iface_wl_buffer wl_buffer
++ * @section page_iface_wl_buffer_desc Description
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ * @section page_iface_wl_buffer_api API
++ * See @ref iface_wl_buffer.
++ */
++/**
++ * @defgroup iface_wl_buffer The wl_buffer interface
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ */
++extern const struct wl_interface wl_buffer_interface;
++#endif
++#ifndef WL_DATA_OFFER_INTERFACE
++#define WL_DATA_OFFER_INTERFACE
++/**
++ * @page page_iface_wl_data_offer wl_data_offer
++ * @section page_iface_wl_data_offer_desc Description
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client).  It is used by the
++ * copy-and-paste and drag-and-drop mechanisms.  The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ * @section page_iface_wl_data_offer_api API
++ * See @ref iface_wl_data_offer.
++ */
++/**
++ * @defgroup iface_wl_data_offer The wl_data_offer interface
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client).  It is used by the
++ * copy-and-paste and drag-and-drop mechanisms.  The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ */
++extern const struct wl_interface wl_data_offer_interface;
++#endif
++#ifndef WL_DATA_SOURCE_INTERFACE
++#define WL_DATA_SOURCE_INTERFACE
++/**
++ * @page page_iface_wl_data_source wl_data_source
++ * @section page_iface_wl_data_source_desc Description
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ * @section page_iface_wl_data_source_api API
++ * See @ref iface_wl_data_source.
++ */
++/**
++ * @defgroup iface_wl_data_source The wl_data_source interface
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ */
++extern const struct wl_interface wl_data_source_interface;
++#endif
++#ifndef WL_DATA_DEVICE_INTERFACE
++#define WL_DATA_DEVICE_INTERFACE
++/**
++ * @page page_iface_wl_data_device wl_data_device
++ * @section page_iface_wl_data_device_desc Description
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ * @section page_iface_wl_data_device_api API
++ * See @ref iface_wl_data_device.
++ */
++/**
++ * @defgroup iface_wl_data_device The wl_data_device interface
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ */
++extern const struct wl_interface wl_data_device_interface;
++#endif
++#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE
++#define WL_DATA_DEVICE_MANAGER_INTERFACE
++/**
++ * @page page_iface_wl_data_device_manager wl_data_device_manager
++ * @section page_iface_wl_data_device_manager_desc Description
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop.  These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ * @section page_iface_wl_data_device_manager_api API
++ * See @ref iface_wl_data_device_manager.
++ */
++/**
++ * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop.  These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ */
++extern const struct wl_interface wl_data_device_manager_interface;
++#endif
++#ifndef WL_SHELL_INTERFACE
++#define WL_SHELL_INTERFACE
++/**
++ * @page page_iface_wl_shell wl_shell
++ * @section page_iface_wl_shell_desc Description
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ * @section page_iface_wl_shell_api API
++ * See @ref iface_wl_shell.
++ */
++/**
++ * @defgroup iface_wl_shell The wl_shell interface
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ */
++extern const struct wl_interface wl_shell_interface;
++#endif
++#ifndef WL_SHELL_SURFACE_INTERFACE
++#define WL_SHELL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_shell_surface wl_shell_surface
++ * @section page_iface_wl_shell_surface_desc Description
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ * @section page_iface_wl_shell_surface_api API
++ * See @ref iface_wl_shell_surface.
++ */
++/**
++ * @defgroup iface_wl_shell_surface The wl_shell_surface interface
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ */
++extern const struct wl_interface wl_shell_surface_interface;
++#endif
++#ifndef WL_SURFACE_INTERFACE
++#define WL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_surface wl_surface
++ * @section page_iface_wl_surface_desc Description
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ * @section page_iface_wl_surface_api API
++ * See @ref iface_wl_surface.
++ */
++/**
++ * @defgroup iface_wl_surface The wl_surface interface
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ */
++extern const struct wl_interface wl_surface_interface;
++#endif
++#ifndef WL_SEAT_INTERFACE
++#define WL_SEAT_INTERFACE
++/**
++ * @page page_iface_wl_seat wl_seat
++ * @section page_iface_wl_seat_desc Description
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged.  A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ * @section page_iface_wl_seat_api API
++ * See @ref iface_wl_seat.
++ */
++/**
++ * @defgroup iface_wl_seat The wl_seat interface
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged.  A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ */
++extern const struct wl_interface wl_seat_interface;
++#endif
++#ifndef WL_POINTER_INTERFACE
++#define WL_POINTER_INTERFACE
++/**
++ * @page page_iface_wl_pointer wl_pointer
++ * @section page_iface_wl_pointer_desc Description
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ * @section page_iface_wl_pointer_api API
++ * See @ref iface_wl_pointer.
++ */
++/**
++ * @defgroup iface_wl_pointer The wl_pointer interface
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ */
++extern const struct wl_interface wl_pointer_interface;
++#endif
++#ifndef WL_KEYBOARD_INTERFACE
++#define WL_KEYBOARD_INTERFACE
++/**
++ * @page page_iface_wl_keyboard wl_keyboard
++ * @section page_iface_wl_keyboard_desc Description
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ * @section page_iface_wl_keyboard_api API
++ * See @ref iface_wl_keyboard.
++ */
++/**
++ * @defgroup iface_wl_keyboard The wl_keyboard interface
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ */
++extern const struct wl_interface wl_keyboard_interface;
++#endif
++#ifndef WL_TOUCH_INTERFACE
++#define WL_TOUCH_INTERFACE
++/**
++ * @page page_iface_wl_touch wl_touch
++ * @section page_iface_wl_touch_desc Description
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ * @section page_iface_wl_touch_api API
++ * See @ref iface_wl_touch.
++ */
++/**
++ * @defgroup iface_wl_touch The wl_touch interface
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ */
++extern const struct wl_interface wl_touch_interface;
++#endif
++#ifndef WL_OUTPUT_INTERFACE
++#define WL_OUTPUT_INTERFACE
++/**
++ * @page page_iface_wl_output wl_output
++ * @section page_iface_wl_output_desc Description
++ *
++ * An output describes part of the compositor geometry.  The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible.  This typically corresponds to a monitor that
++ * displays part of the compositor space.  This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ * @section page_iface_wl_output_api API
++ * See @ref iface_wl_output.
++ */
++/**
++ * @defgroup iface_wl_output The wl_output interface
++ *
++ * An output describes part of the compositor geometry.  The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible.  This typically corresponds to a monitor that
++ * displays part of the compositor space.  This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ */
++extern const struct wl_interface wl_output_interface;
++#endif
++#ifndef WL_REGION_INTERFACE
++#define WL_REGION_INTERFACE
++/**
++ * @page page_iface_wl_region wl_region
++ * @section page_iface_wl_region_desc Description
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ * @section page_iface_wl_region_api API
++ * See @ref iface_wl_region.
++ */
++/**
++ * @defgroup iface_wl_region The wl_region interface
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ */
++extern const struct wl_interface wl_region_interface;
++#endif
++#ifndef WL_SUBCOMPOSITOR_INTERFACE
++#define WL_SUBCOMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_subcompositor wl_subcompositor
++ * @section page_iface_wl_subcompositor_desc Description
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ * @section page_iface_wl_subcompositor_api API
++ * See @ref iface_wl_subcompositor.
++ */
++/**
++ * @defgroup iface_wl_subcompositor The wl_subcompositor interface
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ */
++extern const struct wl_interface wl_subcompositor_interface;
++#endif
++#ifndef WL_SUBSURFACE_INTERFACE
++#define WL_SUBSURFACE_INTERFACE
++/**
++ * @page page_iface_wl_subsurface wl_subsurface
++ * @section page_iface_wl_subsurface_desc Description
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ * @section page_iface_wl_subsurface_api API
++ * See @ref iface_wl_subsurface.
++ */
++/**
++ * @defgroup iface_wl_subsurface The wl_subsurface interface
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ */
++extern const struct wl_interface wl_subsurface_interface;
++#endif
++
++#ifndef WL_DISPLAY_ERROR_ENUM
++#define WL_DISPLAY_ERROR_ENUM
++/**
++ * @ingroup iface_wl_display
++ * global error values
++ *
++ * These errors are global and can be emitted in response to any
++ * server request.
++ */
++enum wl_display_error {
++      /**
++       * server couldn't find object
++       */
++      WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
++      /**
++       * method doesn't exist on the specified interface
++       */
++      WL_DISPLAY_ERROR_INVALID_METHOD = 1,
++      /**
++       * server is out of memory
++       */
++      WL_DISPLAY_ERROR_NO_MEMORY = 2,
++};
++#endif /* WL_DISPLAY_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_display
++ * @struct wl_display_listener
++ */
++struct wl_display_listener {
++      /**
++       * fatal error event
++       *
++       * The error event is sent out when a fatal (non-recoverable)
++       * error has occurred. The object_id argument is the object where
++       * the error occurred, most often in response to a request to that
++       * object. The code identifies the error and is defined by the
++       * object interface. As such, each interface defines its own set of
++       * error codes. The message is a brief description of the error,
++       * for (debugging) convenience.
++       * @param object_id object where the error occurred
++       * @param code error code
++       * @param message error description
++       */
++      void (*error)(void *data,
++                    struct wl_display *wl_display,
++                    void *object_id,
++                    uint32_t code,
++                    const char *message);
++      /**
++       * acknowledge object ID deletion
++       *
++       * This event is used internally by the object ID management
++       * logic. When a client deletes an object, the server will send
++       * this event to acknowledge that it has seen the delete request.
++       * When the client receives this event, it will know that it can
++       * safely reuse the object ID.
++       * @param id deleted object ID
++       */
++      void (*delete_id)(void *data,
++                        struct wl_display *wl_display,
++                        uint32_t id);
++};
++
++/**
++ * @ingroup iface_wl_display
++ */
++static inline int
++wl_display_add_listener(struct wl_display *wl_display,
++                      const struct wl_display_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_display,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_DISPLAY_SYNC 0
++#define WL_DISPLAY_GET_REGISTRY 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_ERROR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1
++
++/** @ingroup iface_wl_display */
++static inline void
++wl_display_set_user_data(struct wl_display *wl_display, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_display, user_data);
++}
++
++/** @ingroup iface_wl_display */
++static inline void *
++wl_display_get_user_data(struct wl_display *wl_display)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_display);
++}
++
++static inline uint32_t
++wl_display_get_version(struct wl_display *wl_display)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_display);
++}
++
++/**
++ * @ingroup iface_wl_display
++ *
++ * The sync request asks the server to emit the 'done' event
++ * on the returned wl_callback object.  Since requests are
++ * handled in-order and events are delivered in-order, this can
++ * be used as a barrier to ensure all previous requests and the
++ * resulting events have been handled.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client must not
++ * attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the event serial.
++ */
++static inline struct wl_callback *
++wl_display_sync(struct wl_display *wl_display)
++{
++      struct wl_proxy *callback;
++
++      callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
++                       WL_DISPLAY_SYNC, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
++
++      return (struct wl_callback *) callback;
++}
++
++/**
++ * @ingroup iface_wl_display
++ *
++ * This request creates a registry object that allows the client
++ * to list and bind the global objects available from the
++ * compositor.
++ */
++static inline struct wl_registry *
++wl_display_get_registry(struct wl_display *wl_display)
++{
++      struct wl_proxy *registry;
++
++      registry = wl_proxy_marshal_flags((struct wl_proxy *) wl_display,
++                       WL_DISPLAY_GET_REGISTRY, &wl_registry_interface, wl_proxy_get_version((struct wl_proxy *) wl_display), 0, NULL);
++
++      return (struct wl_registry *) registry;
++}
++
++/**
++ * @ingroup iface_wl_registry
++ * @struct wl_registry_listener
++ */
++struct wl_registry_listener {
++      /**
++       * announce global object
++       *
++       * Notify the client of global objects.
++       *
++       * The event notifies the client that a global object with the
++       * given name is now available, and it implements the given version
++       * of the given interface.
++       * @param name numeric name of the global object
++       * @param interface interface implemented by the object
++       * @param version interface version
++       */
++      void (*global)(void *data,
++                     struct wl_registry *wl_registry,
++                     uint32_t name,
++                     const char *interface,
++                     uint32_t version);
++      /**
++       * announce removal of global object
++       *
++       * Notify the client of removed global objects.
++       *
++       * This event notifies the client that the global identified by
++       * name is no longer available. If the client bound to the global
++       * using the bind request, the client should now destroy that
++       * object.
++       *
++       * The object remains valid and requests to the object will be
++       * ignored until the client destroys it, to avoid races between the
++       * global going away and a client sending a request to it.
++       * @param name numeric name of the global object
++       */
++      void (*global_remove)(void *data,
++                            struct wl_registry *wl_registry,
++                            uint32_t name);
++};
++
++/**
++ * @ingroup iface_wl_registry
++ */
++static inline int
++wl_registry_add_listener(struct wl_registry *wl_registry,
++                       const struct wl_registry_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_registry,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_REGISTRY_BIND 0
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_BIND_SINCE_VERSION 1
++
++/** @ingroup iface_wl_registry */
++static inline void
++wl_registry_set_user_data(struct wl_registry *wl_registry, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_registry, user_data);
++}
++
++/** @ingroup iface_wl_registry */
++static inline void *
++wl_registry_get_user_data(struct wl_registry *wl_registry)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_registry);
++}
++
++static inline uint32_t
++wl_registry_get_version(struct wl_registry *wl_registry)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_registry);
++}
++
++/** @ingroup iface_wl_registry */
++static inline void
++wl_registry_destroy(struct wl_registry *wl_registry)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_registry);
++}
++
++/**
++ * @ingroup iface_wl_registry
++ *
++ * Binds a new, client-created object to the server using the
++ * specified name as the identifier.
++ */
++static inline void *
++wl_registry_bind(struct wl_registry *wl_registry, uint32_t name, const struct wl_interface *interface, uint32_t version)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_registry,
++                       WL_REGISTRY_BIND, interface, version, 0, name, interface->name, version, NULL);
++
++      return (void *) id;
++}
++
++/**
++ * @ingroup iface_wl_callback
++ * @struct wl_callback_listener
++ */
++struct wl_callback_listener {
++      /**
++       * done event
++       *
++       * Notify the client when the related request is done.
++       * @param callback_data request-specific data for the callback
++       */
++      void (*done)(void *data,
++                   struct wl_callback *wl_callback,
++                   uint32_t callback_data);
++};
++
++/**
++ * @ingroup iface_wl_callback
++ */
++static inline int
++wl_callback_add_listener(struct wl_callback *wl_callback,
++                       const struct wl_callback_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_callback,
++                                   (void (**)(void)) listener, data);
++}
++
++/**
++ * @ingroup iface_wl_callback
++ */
++#define WL_CALLBACK_DONE_SINCE_VERSION 1
++
++
++/** @ingroup iface_wl_callback */
++static inline void
++wl_callback_set_user_data(struct wl_callback *wl_callback, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_callback, user_data);
++}
++
++/** @ingroup iface_wl_callback */
++static inline void *
++wl_callback_get_user_data(struct wl_callback *wl_callback)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_callback);
++}
++
++static inline uint32_t
++wl_callback_get_version(struct wl_callback *wl_callback)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_callback);
++}
++
++/** @ingroup iface_wl_callback */
++static inline void
++wl_callback_destroy(struct wl_callback *wl_callback)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_callback);
++}
++
++#define WL_COMPOSITOR_CREATE_SURFACE 0
++#define WL_COMPOSITOR_CREATE_REGION 1
++
++
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1
++
++/** @ingroup iface_wl_compositor */
++static inline void
++wl_compositor_set_user_data(struct wl_compositor *wl_compositor, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_compositor, user_data);
++}
++
++/** @ingroup iface_wl_compositor */
++static inline void *
++wl_compositor_get_user_data(struct wl_compositor *wl_compositor)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_compositor);
++}
++
++static inline uint32_t
++wl_compositor_get_version(struct wl_compositor *wl_compositor)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_compositor);
++}
++
++/** @ingroup iface_wl_compositor */
++static inline void
++wl_compositor_destroy(struct wl_compositor *wl_compositor)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_compositor);
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ *
++ * Ask the compositor to create a new surface.
++ */
++static inline struct wl_surface *
++wl_compositor_create_surface(struct wl_compositor *wl_compositor)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor,
++                       WL_COMPOSITOR_CREATE_SURFACE, &wl_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL);
++
++      return (struct wl_surface *) id;
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ *
++ * Ask the compositor to create a new region.
++ */
++static inline struct wl_region *
++wl_compositor_create_region(struct wl_compositor *wl_compositor)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_compositor,
++                       WL_COMPOSITOR_CREATE_REGION, &wl_region_interface, wl_proxy_get_version((struct wl_proxy *) wl_compositor), 0, NULL);
++
++      return (struct wl_region *) id;
++}
++
++#define WL_SHM_POOL_CREATE_BUFFER 0
++#define WL_SHM_POOL_DESTROY 1
++#define WL_SHM_POOL_RESIZE 2
++
++
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shm_pool */
++static inline void
++wl_shm_pool_set_user_data(struct wl_shm_pool *wl_shm_pool, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_shm_pool, user_data);
++}
++
++/** @ingroup iface_wl_shm_pool */
++static inline void *
++wl_shm_pool_get_user_data(struct wl_shm_pool *wl_shm_pool)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_shm_pool);
++}
++
++static inline uint32_t
++wl_shm_pool_get_version(struct wl_shm_pool *wl_shm_pool)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_shm_pool);
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * Create a wl_buffer object from the pool.
++ *
++ * The buffer is created offset bytes into the pool and has
++ * width and height as specified.  The stride argument specifies
++ * the number of bytes from the beginning of one row to the beginning
++ * of the next.  The format is the pixel format of the buffer and
++ * must be one of those advertised through the wl_shm.format event.
++ *
++ * A buffer will keep a reference to the pool it was created from
++ * so it is valid to destroy the pool immediately after creating
++ * a buffer from it.
++ */
++static inline struct wl_buffer *
++wl_shm_pool_create_buffer(struct wl_shm_pool *wl_shm_pool, int32_t offset, int32_t width, int32_t height, int32_t stride, uint32_t format)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++                       WL_SHM_POOL_CREATE_BUFFER, &wl_buffer_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, NULL, offset, width, height, stride, format);
++
++      return (struct wl_buffer *) id;
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * Destroy the shared memory pool.
++ *
++ * The mmapped memory will be released when all
++ * buffers that have been created from this pool
++ * are gone.
++ */
++static inline void
++wl_shm_pool_destroy(struct wl_shm_pool *wl_shm_pool)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++                       WL_SHM_POOL_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_shm_pool
++ *
++ * This request will cause the server to remap the backing memory
++ * for the pool from the file descriptor passed when the pool was
++ * created, but using the new size.  This request can only be
++ * used to make the pool bigger.
++ */
++static inline void
++wl_shm_pool_resize(struct wl_shm_pool *wl_shm_pool, int32_t size)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shm_pool,
++                       WL_SHM_POOL_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shm_pool), 0, size);
++}
++
++#ifndef WL_SHM_ERROR_ENUM
++#define WL_SHM_ERROR_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * wl_shm error values
++ *
++ * These errors can be emitted in response to wl_shm requests.
++ */
++enum wl_shm_error {
++      /**
++       * buffer format is not known
++       */
++      WL_SHM_ERROR_INVALID_FORMAT = 0,
++      /**
++       * invalid size or stride during pool or buffer creation
++       */
++      WL_SHM_ERROR_INVALID_STRIDE = 1,
++      /**
++       * mmapping the file descriptor failed
++       */
++      WL_SHM_ERROR_INVALID_FD = 2,
++};
++#endif /* WL_SHM_ERROR_ENUM */
++
++#ifndef WL_SHM_FORMAT_ENUM
++#define WL_SHM_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * pixel formats
++ *
++ * This describes the memory layout of an individual pixel.
++ *
++ * All renderers should support argb8888 and xrgb8888 but any other
++ * formats are optional and may not be supported by the particular
++ * renderer in use.
++ *
++ * The drm format codes match the macros defined in drm_fourcc.h.
++ * The formats actually supported by the compositor will be
++ * reported by the format event.
++ */
++enum wl_shm_format {
++      /**
++       * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_ARGB8888 = 0,
++      /**
++       * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_XRGB8888 = 1,
++      /**
++       * 8-bit color index format, [7:0] C
++       */
++      WL_SHM_FORMAT_C8 = 0x20203843,
++      /**
++       * 8-bit RGB format, [7:0] R:G:B 3:3:2
++       */
++      WL_SHM_FORMAT_RGB332 = 0x38424752,
++      /**
++       * 8-bit BGR format, [7:0] B:G:R 2:3:3
++       */
++      WL_SHM_FORMAT_BGR233 = 0x38524742,
++      /**
++       * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_XRGB4444 = 0x32315258,
++      /**
++       * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_XBGR4444 = 0x32314258,
++      /**
++       * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_RGBX4444 = 0x32315852,
++      /**
++       * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_BGRX4444 = 0x32315842,
++      /**
++       * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_ARGB4444 = 0x32315241,
++      /**
++       * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_ABGR4444 = 0x32314241,
++      /**
++       * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_RGBA4444 = 0x32314152,
++      /**
++       * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_BGRA4444 = 0x32314142,
++      /**
++       * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_XRGB1555 = 0x35315258,
++      /**
++       * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_XBGR1555 = 0x35314258,
++      /**
++       * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_RGBX5551 = 0x35315852,
++      /**
++       * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_BGRX5551 = 0x35315842,
++      /**
++       * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_ARGB1555 = 0x35315241,
++      /**
++       * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_ABGR1555 = 0x35314241,
++      /**
++       * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_RGBA5551 = 0x35314152,
++      /**
++       * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_BGRA5551 = 0x35314142,
++      /**
++       * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian
++       */
++      WL_SHM_FORMAT_RGB565 = 0x36314752,
++      /**
++       * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian
++       */
++      WL_SHM_FORMAT_BGR565 = 0x36314742,
++      /**
++       * 24-bit RGB format, [23:0] R:G:B little endian
++       */
++      WL_SHM_FORMAT_RGB888 = 0x34324752,
++      /**
++       * 24-bit BGR format, [23:0] B:G:R little endian
++       */
++      WL_SHM_FORMAT_BGR888 = 0x34324742,
++      /**
++       * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_XBGR8888 = 0x34324258,
++      /**
++       * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_RGBX8888 = 0x34325852,
++      /**
++       * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_BGRX8888 = 0x34325842,
++      /**
++       * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_ABGR8888 = 0x34324241,
++      /**
++       * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_RGBA8888 = 0x34324152,
++      /**
++       * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_BGRA8888 = 0x34324142,
++      /**
++       * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_XRGB2101010 = 0x30335258,
++      /**
++       * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_XBGR2101010 = 0x30334258,
++      /**
++       * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_RGBX1010102 = 0x30335852,
++      /**
++       * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_BGRX1010102 = 0x30335842,
++      /**
++       * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_ARGB2101010 = 0x30335241,
++      /**
++       * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_ABGR2101010 = 0x30334241,
++      /**
++       * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_RGBA1010102 = 0x30334152,
++      /**
++       * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_BGRA1010102 = 0x30334142,
++      /**
++       * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_YUYV = 0x56595559,
++      /**
++       * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_YVYU = 0x55595659,
++      /**
++       * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_UYVY = 0x59565955,
++      /**
++       * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_VYUY = 0x59555956,
++      /**
++       * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_AYUV = 0x56555941,
++      /**
++       * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane
++       */
++      WL_SHM_FORMAT_NV12 = 0x3231564e,
++      /**
++       * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane
++       */
++      WL_SHM_FORMAT_NV21 = 0x3132564e,
++      /**
++       * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane
++       */
++      WL_SHM_FORMAT_NV16 = 0x3631564e,
++      /**
++       * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane
++       */
++      WL_SHM_FORMAT_NV61 = 0x3136564e,
++      /**
++       * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV410 = 0x39565559,
++      /**
++       * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU410 = 0x39555659,
++      /**
++       * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV411 = 0x31315559,
++      /**
++       * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU411 = 0x31315659,
++      /**
++       * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV420 = 0x32315559,
++      /**
++       * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU420 = 0x32315659,
++      /**
++       * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV422 = 0x36315559,
++      /**
++       * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU422 = 0x36315659,
++      /**
++       * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV444 = 0x34325559,
++      /**
++       * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU444 = 0x34325659,
++};
++#endif /* WL_SHM_FORMAT_ENUM */
++
++/**
++ * @ingroup iface_wl_shm
++ * @struct wl_shm_listener
++ */
++struct wl_shm_listener {
++      /**
++       * pixel format description
++       *
++       * Informs the client about a valid pixel format that can be used
++       * for buffers. Known formats include argb8888 and xrgb8888.
++       * @param format buffer pixel format
++       */
++      void (*format)(void *data,
++                     struct wl_shm *wl_shm,
++                     uint32_t format);
++};
++
++/**
++ * @ingroup iface_wl_shm
++ */
++static inline int
++wl_shm_add_listener(struct wl_shm *wl_shm,
++                  const struct wl_shm_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_shm,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_SHM_CREATE_POOL 0
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_FORMAT_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_CREATE_POOL_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shm */
++static inline void
++wl_shm_set_user_data(struct wl_shm *wl_shm, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_shm, user_data);
++}
++
++/** @ingroup iface_wl_shm */
++static inline void *
++wl_shm_get_user_data(struct wl_shm *wl_shm)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_shm);
++}
++
++static inline uint32_t
++wl_shm_get_version(struct wl_shm *wl_shm)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_shm);
++}
++
++/** @ingroup iface_wl_shm */
++static inline void
++wl_shm_destroy(struct wl_shm *wl_shm)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_shm);
++}
++
++/**
++ * @ingroup iface_wl_shm
++ *
++ * Create a new wl_shm_pool object.
++ *
++ * The pool can be used to create shared memory based buffer
++ * objects.  The server will mmap size bytes of the passed file
++ * descriptor, to use as backing memory for the pool.
++ */
++static inline struct wl_shm_pool *
++wl_shm_create_pool(struct wl_shm *wl_shm, int32_t fd, int32_t size)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shm,
++                       WL_SHM_CREATE_POOL, &wl_shm_pool_interface, wl_proxy_get_version((struct wl_proxy *) wl_shm), 0, NULL, fd, size);
++
++      return (struct wl_shm_pool *) id;
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ * @struct wl_buffer_listener
++ */
++struct wl_buffer_listener {
++      /**
++       * compositor releases buffer
++       *
++       * Sent when this wl_buffer is no longer used by the compositor.
++       * The client is now free to reuse or destroy this buffer and its
++       * backing storage.
++       *
++       * If a client receives a release event before the frame callback
++       * requested in the same wl_surface.commit that attaches this
++       * wl_buffer to a surface, then the client is immediately free to
++       * reuse the buffer and its backing storage, and does not need a
++       * second buffer for the next surface content update. Typically
++       * this is possible, when the compositor maintains a copy of the
++       * wl_surface contents, e.g. as a GL texture. This is an important
++       * optimization for GL(ES) compositors with wl_shm clients.
++       */
++      void (*release)(void *data,
++                      struct wl_buffer *wl_buffer);
++};
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++static inline int
++wl_buffer_add_listener(struct wl_buffer *wl_buffer,
++                     const struct wl_buffer_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_buffer,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_BUFFER_DESTROY 0
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_RELEASE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_wl_buffer */
++static inline void
++wl_buffer_set_user_data(struct wl_buffer *wl_buffer, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_buffer, user_data);
++}
++
++/** @ingroup iface_wl_buffer */
++static inline void *
++wl_buffer_get_user_data(struct wl_buffer *wl_buffer)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_buffer);
++}
++
++static inline uint32_t
++wl_buffer_get_version(struct wl_buffer *wl_buffer)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_buffer);
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ *
++ * Destroy a buffer. If and how you need to release the backing
++ * storage is defined by the buffer factory interface.
++ *
++ * For possible side-effects to a surface, see wl_surface.attach.
++ */
++static inline void
++wl_buffer_destroy(struct wl_buffer *wl_buffer)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_buffer,
++                       WL_BUFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_buffer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_DATA_OFFER_ERROR_ENUM
++#define WL_DATA_OFFER_ERROR_ENUM
++enum wl_data_offer_error {
++      /**
++       * finish request was called untimely
++       */
++      WL_DATA_OFFER_ERROR_INVALID_FINISH = 0,
++      /**
++       * action mask contains invalid values
++       */
++      WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1,
++      /**
++       * action argument has an invalid value
++       */
++      WL_DATA_OFFER_ERROR_INVALID_ACTION = 2,
++      /**
++       * offer doesn't accept this request
++       */
++      WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
++};
++#endif /* WL_DATA_OFFER_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_offer
++ * @struct wl_data_offer_listener
++ */
++struct wl_data_offer_listener {
++      /**
++       * advertise offered mime type
++       *
++       * Sent immediately after creating the wl_data_offer object. One
++       * event per offered mime type.
++       * @param mime_type offered mime type
++       */
++      void (*offer)(void *data,
++                    struct wl_data_offer *wl_data_offer,
++                    const char *mime_type);
++      /**
++       * notify the source-side available actions
++       *
++       * This event indicates the actions offered by the data source.
++       * It will be sent right after wl_data_device.enter, or anytime the
++       * source side changes its offered actions through
++       * wl_data_source.set_actions.
++       * @param source_actions actions offered by the data source
++       * @since 3
++       */
++      void (*source_actions)(void *data,
++                             struct wl_data_offer *wl_data_offer,
++                             uint32_t source_actions);
++      /**
++       * notify the selected action
++       *
++       * This event indicates the action selected by the compositor
++       * after matching the source/destination side actions. Only one
++       * action (or none) will be offered here.
++       *
++       * This event can be emitted multiple times during the
++       * drag-and-drop operation in response to destination side action
++       * changes through wl_data_offer.set_actions.
++       *
++       * This event will no longer be emitted after wl_data_device.drop
++       * happened on the drag-and-drop destination, the client must honor
++       * the last action received, or the last preferred one set through
++       * wl_data_offer.set_actions when handling an "ask" action.
++       *
++       * Compositors may also change the selected action on the fly,
++       * mainly in response to keyboard modifier changes during the
++       * drag-and-drop operation.
++       *
++       * The most recent action received is always the valid one. Prior
++       * to receiving wl_data_device.drop, the chosen action may change
++       * (e.g. due to keyboard modifiers being pressed). At the time of
++       * receiving wl_data_device.drop the drag-and-drop destination must
++       * honor the last action received.
++       *
++       * Action changes may still happen after wl_data_device.drop,
++       * especially on "ask" actions, where the drag-and-drop destination
++       * may choose another action afterwards. Action changes happening
++       * at this stage are always the result of inter-client negotiation,
++       * the compositor shall no longer be able to induce a different
++       * action.
++       *
++       * Upon "ask" actions, it is expected that the drag-and-drop
++       * destination may potentially choose a different action and/or
++       * mime type, based on wl_data_offer.source_actions and finally
++       * chosen by the user (e.g. popping up a menu with the available
++       * options). The final wl_data_offer.set_actions and
++       * wl_data_offer.accept requests must happen before the call to
++       * wl_data_offer.finish.
++       * @param dnd_action action selected by the compositor
++       * @since 3
++       */
++      void (*action)(void *data,
++                     struct wl_data_offer *wl_data_offer,
++                     uint32_t dnd_action);
++};
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++static inline int
++wl_data_offer_add_listener(struct wl_data_offer *wl_data_offer,
++                         const struct wl_data_offer_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_data_offer,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_OFFER_ACCEPT 0
++#define WL_DATA_OFFER_RECEIVE 1
++#define WL_DATA_OFFER_DESTROY 2
++#define WL_DATA_OFFER_FINISH 3
++#define WL_DATA_OFFER_SET_ACTIONS 4
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3
++
++/** @ingroup iface_wl_data_offer */
++static inline void
++wl_data_offer_set_user_data(struct wl_data_offer *wl_data_offer, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_data_offer, user_data);
++}
++
++/** @ingroup iface_wl_data_offer */
++static inline void *
++wl_data_offer_get_user_data(struct wl_data_offer *wl_data_offer)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_data_offer);
++}
++
++static inline uint32_t
++wl_data_offer_get_version(struct wl_data_offer *wl_data_offer)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_data_offer);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Indicate that the client can accept the given mime type, or
++ * NULL for not accepted.
++ *
++ * For objects of version 2 or older, this request is used by the
++ * client to give feedback whether the client can receive the given
++ * mime type, or NULL if none is accepted; the feedback does not
++ * determine whether the drag-and-drop operation succeeds or not.
++ *
++ * For objects of version 3 or newer, this request determines the
++ * final result of the drag-and-drop operation. If the end result
++ * is that no mime types were accepted, the drag-and-drop operation
++ * will be cancelled and the corresponding drag source will receive
++ * wl_data_source.cancelled. Clients may still use this event in
++ * conjunction with wl_data_source.action for feedback.
++ */
++static inline void
++wl_data_offer_accept(struct wl_data_offer *wl_data_offer, uint32_t serial, const char *mime_type)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++                       WL_DATA_OFFER_ACCEPT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, serial, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * To transfer the offered data, the client issues this request
++ * and indicates the mime type it wants to receive.  The transfer
++ * happens through the passed file descriptor (typically created
++ * with the pipe system call).  The source client writes the data
++ * in the mime type representation requested and then closes the
++ * file descriptor.
++ *
++ * The receiving client reads from the read end of the pipe until
++ * EOF and then closes its end, at which point the transfer is
++ * complete.
++ *
++ * This request may happen multiple times for different mime types,
++ * both before and after wl_data_device.drop. Drag-and-drop destination
++ * clients may preemptively fetch data or examine it more closely to
++ * determine acceptance.
++ */
++static inline void
++wl_data_offer_receive(struct wl_data_offer *wl_data_offer, const char *mime_type, int32_t fd)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++                       WL_DATA_OFFER_RECEIVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, mime_type, fd);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Destroy the data offer.
++ */
++static inline void
++wl_data_offer_destroy(struct wl_data_offer *wl_data_offer)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++                       WL_DATA_OFFER_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Notifies the compositor that the drag destination successfully
++ * finished the drag-and-drop operation.
++ *
++ * Upon receiving this request, the compositor will emit
++ * wl_data_source.dnd_finished on the drag source client.
++ *
++ * It is a client error to perform other requests than
++ * wl_data_offer.destroy after this one. It is also an error to perform
++ * this request after a NULL mime type has been set in
++ * wl_data_offer.accept or no action was received through
++ * wl_data_offer.action.
++ */
++static inline void
++wl_data_offer_finish(struct wl_data_offer *wl_data_offer)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++                       WL_DATA_OFFER_FINISH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ *
++ * Sets the actions that the destination side client supports for
++ * this operation. This request may trigger the emission of
++ * wl_data_source.action and wl_data_offer.action events if the compositor
++ * needs to change the selected action.
++ *
++ * This request can be called multiple times throughout the
++ * drag-and-drop operation, typically in response to wl_data_device.enter
++ * or wl_data_device.motion events.
++ *
++ * This request determines the final result of the drag-and-drop
++ * operation. If the end result is that no action is accepted,
++ * the drag source will receive wl_drag_source.cancelled.
++ *
++ * The dnd_actions argument must contain only values expressed in the
++ * wl_data_device_manager.dnd_actions enum, and the preferred_action
++ * argument must only contain one of those values set, otherwise it
++ * will result in a protocol error.
++ *
++ * While managing an "ask" action, the destination drag-and-drop client
++ * may perform further wl_data_offer.receive requests, and is expected
++ * to perform one last wl_data_offer.set_actions request with a preferred
++ * action other than "ask" (and optionally wl_data_offer.accept) before
++ * requesting wl_data_offer.finish, in order to convey the action selected
++ * by the user. If the preferred action is not in the
++ * wl_data_offer.source_actions mask, an error will be raised.
++ *
++ * If the "ask" action is dismissed (e.g. user cancellation), the client
++ * is expected to perform wl_data_offer.destroy right away.
++ *
++ * This request can only be made on drag-and-drop offers, a protocol error
++ * will be raised otherwise.
++ */
++static inline void
++wl_data_offer_set_actions(struct wl_data_offer *wl_data_offer, uint32_t dnd_actions, uint32_t preferred_action)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_offer,
++                       WL_DATA_OFFER_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_offer), 0, dnd_actions, preferred_action);
++}
++
++#ifndef WL_DATA_SOURCE_ERROR_ENUM
++#define WL_DATA_SOURCE_ERROR_ENUM
++enum wl_data_source_error {
++      /**
++       * action mask contains invalid values
++       */
++      WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0,
++      /**
++       * source doesn't accept this request
++       */
++      WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
++};
++#endif /* WL_DATA_SOURCE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_source
++ * @struct wl_data_source_listener
++ */
++struct wl_data_source_listener {
++      /**
++       * a target accepts an offered mime type
++       *
++       * Sent when a target accepts pointer_focus or motion events. If
++       * a target does not accept any of the offered types, type is NULL.
++       *
++       * Used for feedback during drag-and-drop.
++       * @param mime_type mime type accepted by the target
++       */
++      void (*target)(void *data,
++                     struct wl_data_source *wl_data_source,
++                     const char *mime_type);
++      /**
++       * send the data
++       *
++       * Request for data from the client. Send the data as the
++       * specified mime type over the passed file descriptor, then close
++       * it.
++       * @param mime_type mime type for the data
++       * @param fd file descriptor for the data
++       */
++      void (*send)(void *data,
++                   struct wl_data_source *wl_data_source,
++                   const char *mime_type,
++                   int32_t fd);
++      /**
++       * selection was cancelled
++       *
++       * This data source is no longer valid. There are several reasons
++       * why this could happen:
++       *
++       * - The data source has been replaced by another data source. -
++       * The drag-and-drop operation was performed, but the drop
++       * destination did not accept any of the mime types offered through
++       * wl_data_source.target. - The drag-and-drop operation was
++       * performed, but the drop destination did not select any of the
++       * actions present in the mask offered through
++       * wl_data_source.action. - The drag-and-drop operation was
++       * performed but didn't happen over a surface. - The compositor
++       * cancelled the drag-and-drop operation (e.g. compositor dependent
++       * timeouts to avoid stale drag-and-drop transfers).
++       *
++       * The client should clean up and destroy this data source.
++       *
++       * For objects of version 2 or older, wl_data_source.cancelled will
++       * only be emitted if the data source was replaced by another data
++       * source.
++       */
++      void (*cancelled)(void *data,
++                        struct wl_data_source *wl_data_source);
++      /**
++       * the drag-and-drop operation physically finished
++       *
++       * The user performed the drop action. This event does not
++       * indicate acceptance, wl_data_source.cancelled may still be
++       * emitted afterwards if the drop destination does not accept any
++       * mime type.
++       *
++       * However, this event might however not be received if the
++       * compositor cancelled the drag-and-drop operation before this
++       * event could happen.
++       *
++       * Note that the data_source may still be used in the future and
++       * should not be destroyed here.
++       * @since 3
++       */
++      void (*dnd_drop_performed)(void *data,
++                                 struct wl_data_source *wl_data_source);
++      /**
++       * the drag-and-drop operation concluded
++       *
++       * The drop destination finished interoperating with this data
++       * source, so the client is now free to destroy this data source
++       * and free all associated data.
++       *
++       * If the action used to perform the operation was "move", the
++       * source can now delete the transferred data.
++       * @since 3
++       */
++      void (*dnd_finished)(void *data,
++                           struct wl_data_source *wl_data_source);
++      /**
++       * notify the selected action
++       *
++       * This event indicates the action selected by the compositor
++       * after matching the source/destination side actions. Only one
++       * action (or none) will be offered here.
++       *
++       * This event can be emitted multiple times during the
++       * drag-and-drop operation, mainly in response to destination side
++       * changes through wl_data_offer.set_actions, and as the data
++       * device enters/leaves surfaces.
++       *
++       * It is only possible to receive this event after
++       * wl_data_source.dnd_drop_performed if the drag-and-drop operation
++       * ended in an "ask" action, in which case the final
++       * wl_data_source.action event will happen immediately before
++       * wl_data_source.dnd_finished.
++       *
++       * Compositors may also change the selected action on the fly,
++       * mainly in response to keyboard modifier changes during the
++       * drag-and-drop operation.
++       *
++       * The most recent action received is always the valid one. The
++       * chosen action may change alongside negotiation (e.g. an "ask"
++       * action can turn into a "move" operation), so the effects of the
++       * final action must always be applied in
++       * wl_data_offer.dnd_finished.
++       *
++       * Clients can trigger cursor surface changes from this point, so
++       * they reflect the current action.
++       * @param dnd_action action selected by the compositor
++       * @since 3
++       */
++      void (*action)(void *data,
++                     struct wl_data_source *wl_data_source,
++                     uint32_t dnd_action);
++};
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++static inline int
++wl_data_source_add_listener(struct wl_data_source *wl_data_source,
++                          const struct wl_data_source_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_data_source,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_SOURCE_OFFER 0
++#define WL_DATA_SOURCE_DESTROY 1
++#define WL_DATA_SOURCE_SET_ACTIONS 2
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3
++
++/** @ingroup iface_wl_data_source */
++static inline void
++wl_data_source_set_user_data(struct wl_data_source *wl_data_source, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_data_source, user_data);
++}
++
++/** @ingroup iface_wl_data_source */
++static inline void *
++wl_data_source_get_user_data(struct wl_data_source *wl_data_source)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_data_source);
++}
++
++static inline uint32_t
++wl_data_source_get_version(struct wl_data_source *wl_data_source)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_data_source);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * This request adds a mime type to the set of mime types
++ * advertised to targets.  Can be called several times to offer
++ * multiple types.
++ */
++static inline void
++wl_data_source_offer(struct wl_data_source *wl_data_source, const char *mime_type)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++                       WL_DATA_SOURCE_OFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * Destroy the data source.
++ */
++static inline void
++wl_data_source_destroy(struct wl_data_source *wl_data_source)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++                       WL_DATA_SOURCE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ *
++ * Sets the actions that the source side client supports for this
++ * operation. This request may trigger wl_data_source.action and
++ * wl_data_offer.action events if the compositor needs to change the
++ * selected action.
++ *
++ * The dnd_actions argument must contain only values expressed in the
++ * wl_data_device_manager.dnd_actions enum, otherwise it will result
++ * in a protocol error.
++ *
++ * This request must be made once only, and can only be made on sources
++ * used in drag-and-drop, so it must be performed before
++ * wl_data_device.start_drag. Attempting to use the source other than
++ * for drag-and-drop will raise a protocol error.
++ */
++static inline void
++wl_data_source_set_actions(struct wl_data_source *wl_data_source, uint32_t dnd_actions)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_source,
++                       WL_DATA_SOURCE_SET_ACTIONS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_source), 0, dnd_actions);
++}
++
++#ifndef WL_DATA_DEVICE_ERROR_ENUM
++#define WL_DATA_DEVICE_ERROR_ENUM
++enum wl_data_device_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_DATA_DEVICE_ERROR_ROLE = 0,
++};
++#endif /* WL_DATA_DEVICE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device
++ * @struct wl_data_device_listener
++ */
++struct wl_data_device_listener {
++      /**
++       * introduce a new wl_data_offer
++       *
++       * The data_offer event introduces a new wl_data_offer object,
++       * which will subsequently be used in either the data_device.enter
++       * event (for drag-and-drop) or the data_device.selection event
++       * (for selections). Immediately following the
++       * data_device.data_offer event, the new data_offer object will
++       * send out data_offer.offer events to describe the mime types it
++       * offers.
++       * @param id the new data_offer object
++       */
++      void (*data_offer)(void *data,
++                         struct wl_data_device *wl_data_device,
++                         struct wl_data_offer *id);
++      /**
++       * initiate drag-and-drop session
++       *
++       * This event is sent when an active drag-and-drop pointer enters
++       * a surface owned by the client. The position of the pointer at
++       * enter time is provided by the x and y arguments, in
++       * surface-local coordinates.
++       * @param serial serial number of the enter event
++       * @param surface client surface entered
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       * @param id source data_offer object
++       */
++      void (*enter)(void *data,
++                    struct wl_data_device *wl_data_device,
++                    uint32_t serial,
++                    struct wl_surface *surface,
++                    wl_fixed_t x,
++                    wl_fixed_t y,
++                    struct wl_data_offer *id);
++      /**
++       * end drag-and-drop session
++       *
++       * This event is sent when the drag-and-drop pointer leaves the
++       * surface and the session ends. The client must destroy the
++       * wl_data_offer introduced at enter time at this point.
++       */
++      void (*leave)(void *data,
++                    struct wl_data_device *wl_data_device);
++      /**
++       * drag-and-drop session motion
++       *
++       * This event is sent when the drag-and-drop pointer moves within
++       * the currently focused surface. The new position of the pointer
++       * is provided by the x and y arguments, in surface-local
++       * coordinates.
++       * @param time timestamp with millisecond granularity
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       */
++      void (*motion)(void *data,
++                     struct wl_data_device *wl_data_device,
++                     uint32_t time,
++                     wl_fixed_t x,
++                     wl_fixed_t y);
++      /**
++       * end drag-and-drop session successfully
++       *
++       * The event is sent when a drag-and-drop operation is ended
++       * because the implicit grab is removed.
++       *
++       * The drag-and-drop destination is expected to honor the last
++       * action received through wl_data_offer.action, if the resulting
++       * action is "copy" or "move", the destination can still perform
++       * wl_data_offer.receive requests, and is expected to end all
++       * transfers with a wl_data_offer.finish request.
++       *
++       * If the resulting action is "ask", the action will not be
++       * considered final. The drag-and-drop destination is expected to
++       * perform one last wl_data_offer.set_actions request, or
++       * wl_data_offer.destroy in order to cancel the operation.
++       */
++      void (*drop)(void *data,
++                   struct wl_data_device *wl_data_device);
++      /**
++       * advertise new selection
++       *
++       * The selection event is sent out to notify the client of a new
++       * wl_data_offer for the selection for this device. The
++       * data_device.data_offer and the data_offer.offer events are sent
++       * out immediately before this event to introduce the data offer
++       * object. The selection event is sent to a client immediately
++       * before receiving keyboard focus and when a new selection is set
++       * while the client has keyboard focus. The data_offer is valid
++       * until a new data_offer or NULL is received or until the client
++       * loses keyboard focus. The client must destroy the previous
++       * selection data_offer, if any, upon receiving this event.
++       * @param id selection data_offer object
++       */
++      void (*selection)(void *data,
++                        struct wl_data_device *wl_data_device,
++                        struct wl_data_offer *id);
++};
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++static inline int
++wl_data_device_add_listener(struct wl_data_device *wl_data_device,
++                          const struct wl_data_device_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_data_device,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_DATA_DEVICE_START_DRAG 0
++#define WL_DATA_DEVICE_SET_SELECTION 1
++#define WL_DATA_DEVICE_RELEASE 2
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2
++
++/** @ingroup iface_wl_data_device */
++static inline void
++wl_data_device_set_user_data(struct wl_data_device *wl_data_device, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_data_device, user_data);
++}
++
++/** @ingroup iface_wl_data_device */
++static inline void *
++wl_data_device_get_user_data(struct wl_data_device *wl_data_device)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device);
++}
++
++static inline uint32_t
++wl_data_device_get_version(struct wl_data_device *wl_data_device)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_data_device);
++}
++
++/** @ingroup iface_wl_data_device */
++static inline void
++wl_data_device_destroy(struct wl_data_device *wl_data_device)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_data_device);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request asks the compositor to start a drag-and-drop
++ * operation on behalf of the client.
++ *
++ * The source argument is the data source that provides the data
++ * for the eventual data transfer. If source is NULL, enter, leave
++ * and motion events are sent only to the client that initiated the
++ * drag and the client is expected to handle the data passing
++ * internally.
++ *
++ * The origin surface is the surface where the drag originates and
++ * the client must have an active implicit grab that matches the
++ * serial.
++ *
++ * The icon surface is an optional (can be NULL) surface that
++ * provides an icon to be moved around with the cursor.  Initially,
++ * the top-left corner of the icon surface is placed at the cursor
++ * hotspot, but subsequent wl_surface.attach request can move the
++ * relative position. Attach requests must be confirmed with
++ * wl_surface.commit as usual. The icon surface is given the role of
++ * a drag-and-drop icon. If the icon surface already has another role,
++ * it raises a protocol error.
++ *
++ * The current and pending input regions of the icon wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the icon surface. When the use
++ * as an icon ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ */
++static inline void
++wl_data_device_start_drag(struct wl_data_device *wl_data_device, struct wl_data_source *source, struct wl_surface *origin, struct wl_surface *icon, uint32_t serial)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++                       WL_DATA_DEVICE_START_DRAG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, origin, icon, serial);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request asks the compositor to set the selection
++ * to the data from the source on behalf of the client.
++ *
++ * To unset the selection, set the source to NULL.
++ */
++static inline void
++wl_data_device_set_selection(struct wl_data_device *wl_data_device, struct wl_data_source *source, uint32_t serial)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++                       WL_DATA_DEVICE_SET_SELECTION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), 0, source, serial);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ *
++ * This request destroys the data device.
++ */
++static inline void
++wl_data_device_release(struct wl_data_device *wl_data_device)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device,
++                       WL_DATA_DEVICE_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_data_device), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++/**
++ * @ingroup iface_wl_data_device_manager
++ * drag and drop actions
++ *
++ * This is a bitmask of the available/preferred actions in a
++ * drag-and-drop operation.
++ *
++ * In the compositor, the selected action is a result of matching the
++ * actions offered by the source and destination sides.  "action" events
++ * with a "none" action will be sent to both source and destination if
++ * there is no match. All further checks will effectively happen on
++ * (source actions ∩ destination actions).
++ *
++ * In addition, compositors may also pick different actions in
++ * reaction to key modifiers being pressed. One common design that
++ * is used in major toolkits (and the behavior recommended for
++ * compositors) is:
++ *
++ * - If no modifiers are pressed, the first match (in bit order)
++ * will be used.
++ * - Pressing Shift selects "move", if enabled in the mask.
++ * - Pressing Control selects "copy", if enabled in the mask.
++ *
++ * Behavior beyond that is considered implementation-dependent.
++ * Compositors may for example bind other modifiers (like Alt/Meta)
++ * or drags initiated with other buttons than BTN_LEFT to specific
++ * actions (e.g. "ask").
++ */
++enum wl_data_device_manager_dnd_action {
++      /**
++       * no action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0,
++      /**
++       * copy action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1,
++      /**
++       * move action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2,
++      /**
++       * ask action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
++};
++#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
++
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE 0
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE 1
++
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void
++wl_data_device_manager_set_user_data(struct wl_data_device_manager *wl_data_device_manager, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_data_device_manager, user_data);
++}
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void *
++wl_data_device_manager_get_user_data(struct wl_data_device_manager *wl_data_device_manager)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_data_device_manager);
++}
++
++static inline uint32_t
++wl_data_device_manager_get_version(struct wl_data_device_manager *wl_data_device_manager)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager);
++}
++
++/** @ingroup iface_wl_data_device_manager */
++static inline void
++wl_data_device_manager_destroy(struct wl_data_device_manager *wl_data_device_manager)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_data_device_manager);
++}
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ *
++ * Create a new data source.
++ */
++static inline struct wl_data_source *
++wl_data_device_manager_create_data_source(struct wl_data_device_manager *wl_data_device_manager)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager,
++                       WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE, &wl_data_source_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL);
++
++      return (struct wl_data_source *) id;
++}
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ *
++ * Create a new data device for a given seat.
++ */
++static inline struct wl_data_device *
++wl_data_device_manager_get_data_device(struct wl_data_device_manager *wl_data_device_manager, struct wl_seat *seat)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_data_device_manager,
++                       WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE, &wl_data_device_interface, wl_proxy_get_version((struct wl_proxy *) wl_data_device_manager), 0, NULL, seat);
++
++      return (struct wl_data_device *) id;
++}
++
++#ifndef WL_SHELL_ERROR_ENUM
++#define WL_SHELL_ERROR_ENUM
++enum wl_shell_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_SHELL_ERROR_ROLE = 0,
++};
++#endif /* WL_SHELL_ERROR_ENUM */
++
++#define WL_SHELL_GET_SHELL_SURFACE 0
++
++
++/**
++ * @ingroup iface_wl_shell
++ */
++#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shell */
++static inline void
++wl_shell_set_user_data(struct wl_shell *wl_shell, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_shell, user_data);
++}
++
++/** @ingroup iface_wl_shell */
++static inline void *
++wl_shell_get_user_data(struct wl_shell *wl_shell)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_shell);
++}
++
++static inline uint32_t
++wl_shell_get_version(struct wl_shell *wl_shell)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_shell);
++}
++
++/** @ingroup iface_wl_shell */
++static inline void
++wl_shell_destroy(struct wl_shell *wl_shell)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_shell);
++}
++
++/**
++ * @ingroup iface_wl_shell
++ *
++ * Create a shell surface for an existing surface. This gives
++ * the wl_surface the role of a shell surface. If the wl_surface
++ * already has another role, it raises a protocol error.
++ *
++ * Only one shell surface can be associated with a given surface.
++ */
++static inline struct wl_shell_surface *
++wl_shell_get_shell_surface(struct wl_shell *wl_shell, struct wl_surface *surface)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_shell,
++                       WL_SHELL_GET_SHELL_SURFACE, &wl_shell_surface_interface, wl_proxy_get_version((struct wl_proxy *) wl_shell), 0, NULL, surface);
++
++      return (struct wl_shell_surface *) id;
++}
++
++#ifndef WL_SHELL_SURFACE_RESIZE_ENUM
++#define WL_SHELL_SURFACE_RESIZE_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * edge values for resizing
++ *
++ * These values are used to indicate which edge of a surface
++ * is being dragged in a resize operation. The server may
++ * use this information to adapt its behavior, e.g. choose
++ * an appropriate cursor image.
++ */
++enum wl_shell_surface_resize {
++      /**
++       * no edge
++       */
++      WL_SHELL_SURFACE_RESIZE_NONE = 0,
++      /**
++       * top edge
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP = 1,
++      /**
++       * bottom edge
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM = 2,
++      /**
++       * left edge
++       */
++      WL_SHELL_SURFACE_RESIZE_LEFT = 4,
++      /**
++       * top and left edges
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5,
++      /**
++       * bottom and left edges
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6,
++      /**
++       * right edge
++       */
++      WL_SHELL_SURFACE_RESIZE_RIGHT = 8,
++      /**
++       * top and right edges
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9,
++      /**
++       * bottom and right edges
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
++};
++#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
++
++#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
++#define WL_SHELL_SURFACE_TRANSIENT_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * details of transient behaviour
++ *
++ * These flags specify details of the expected behaviour
++ * of transient surfaces. Used in the set_transient request.
++ */
++enum wl_shell_surface_transient {
++      /**
++       * do not set keyboard focus
++       */
++      WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
++};
++#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
++
++#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * different method to set the surface fullscreen
++ *
++ * Hints to indicate to the compositor how to deal with a conflict
++ * between the dimensions of the surface and the dimensions of the
++ * output. The compositor is free to ignore this parameter.
++ */
++enum wl_shell_surface_fullscreen_method {
++      /**
++       * no preference, apply default policy
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0,
++      /**
++       * scale, preserve the surface's aspect ratio and center on output
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1,
++      /**
++       * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2,
++      /**
++       * no upscaling, center on output and add black borders to compensate size mismatch
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
++};
++#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * @struct wl_shell_surface_listener
++ */
++struct wl_shell_surface_listener {
++      /**
++       * ping client
++       *
++       * Ping a client to check if it is receiving events and sending
++       * requests. A client is expected to reply with a pong request.
++       * @param serial serial number of the ping
++       */
++      void (*ping)(void *data,
++                   struct wl_shell_surface *wl_shell_surface,
++                   uint32_t serial);
++      /**
++       * suggest resize
++       *
++       * The configure event asks the client to resize its surface.
++       *
++       * The size is a hint, in the sense that the client is free to
++       * ignore it if it doesn't resize, pick a smaller size (to satisfy
++       * aspect ratio or resize in steps of NxM pixels).
++       *
++       * The edges parameter provides a hint about how the surface was
++       * resized. The client may use this information to decide how to
++       * adjust its content to the new size (e.g. a scrolling area might
++       * adjust its content position to leave the viewable content
++       * unmoved).
++       *
++       * The client is free to dismiss all but the last configure event
++       * it received.
++       *
++       * The width and height arguments specify the size of the window in
++       * surface-local coordinates.
++       * @param edges how the surface was resized
++       * @param width new width of the surface
++       * @param height new height of the surface
++       */
++      void (*configure)(void *data,
++                        struct wl_shell_surface *wl_shell_surface,
++                        uint32_t edges,
++                        int32_t width,
++                        int32_t height);
++      /**
++       * popup interaction is done
++       *
++       * The popup_done event is sent out when a popup grab is broken,
++       * that is, when the user clicks a surface that doesn't belong to
++       * the client owning the popup surface.
++       */
++      void (*popup_done)(void *data,
++                         struct wl_shell_surface *wl_shell_surface);
++};
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++static inline int
++wl_shell_surface_add_listener(struct wl_shell_surface *wl_shell_surface,
++                            const struct wl_shell_surface_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_shell_surface,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_SHELL_SURFACE_PONG 0
++#define WL_SHELL_SURFACE_MOVE 1
++#define WL_SHELL_SURFACE_RESIZE 2
++#define WL_SHELL_SURFACE_SET_TOPLEVEL 3
++#define WL_SHELL_SURFACE_SET_TRANSIENT 4
++#define WL_SHELL_SURFACE_SET_FULLSCREEN 5
++#define WL_SHELL_SURFACE_SET_POPUP 6
++#define WL_SHELL_SURFACE_SET_MAXIMIZED 7
++#define WL_SHELL_SURFACE_SET_TITLE 8
++#define WL_SHELL_SURFACE_SET_CLASS 9
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1
++
++/** @ingroup iface_wl_shell_surface */
++static inline void
++wl_shell_surface_set_user_data(struct wl_shell_surface *wl_shell_surface, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_shell_surface, user_data);
++}
++
++/** @ingroup iface_wl_shell_surface */
++static inline void *
++wl_shell_surface_get_user_data(struct wl_shell_surface *wl_shell_surface)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_shell_surface);
++}
++
++static inline uint32_t
++wl_shell_surface_get_version(struct wl_shell_surface *wl_shell_surface)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_shell_surface);
++}
++
++/** @ingroup iface_wl_shell_surface */
++static inline void
++wl_shell_surface_destroy(struct wl_shell_surface *wl_shell_surface)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_shell_surface);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * A client must respond to a ping event with a pong request or
++ * the client may be deemed unresponsive.
++ */
++static inline void
++wl_shell_surface_pong(struct wl_shell_surface *wl_shell_surface, uint32_t serial)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_PONG, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Start a pointer-driven move of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore move requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ */
++static inline void
++wl_shell_surface_move(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_MOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Start a pointer-driven resizing of the surface.
++ *
++ * This request must be used in response to a button press event.
++ * The server may ignore resize requests depending on the state of
++ * the surface (e.g. fullscreen or maximized).
++ */
++static inline void
++wl_shell_surface_resize(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, uint32_t edges)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_RESIZE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, edges);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a toplevel surface.
++ *
++ * A toplevel surface is not fullscreen, maximized or transient.
++ */
++static inline void
++wl_shell_surface_set_toplevel(struct wl_shell_surface *wl_shell_surface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_TOPLEVEL, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface relative to an existing surface.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ *
++ * The flags argument controls details of the transient behaviour.
++ */
++static inline void
++wl_shell_surface_set_transient(struct wl_shell_surface *wl_shell_surface, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_TRANSIENT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, parent, x, y, flags);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a fullscreen surface.
++ *
++ * If an output parameter is given then the surface will be made
++ * fullscreen on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The client may specify a method to resolve a size conflict
++ * between the output size and the surface size - this is provided
++ * through the method parameter.
++ *
++ * The framerate parameter is used only when the method is set
++ * to "driver", to indicate the preferred framerate. A value of 0
++ * indicates that the client does not care about framerate.  The
++ * framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++ *
++ * A method of "scale" or "driver" implies a scaling operation of
++ * the surface, either via a direct scaling operation or a change of
++ * the output mode. This will override any kind of output scaling, so
++ * that mapping a surface with a buffer size equal to the mode can
++ * fill the screen independent of buffer_scale.
++ *
++ * A method of "fill" means we don't scale up the buffer, however
++ * any output scale is applied. This means that you may run into
++ * an edge case where the application maps a buffer with the same
++ * size of the output mode but buffer_scale 1 (thus making a
++ * surface larger than the output). In this case it is allowed to
++ * downscale the results to fit the screen.
++ *
++ * The compositor must reply to this request with a configure event
++ * with the dimensions for the output on which the surface will
++ * be made fullscreen.
++ */
++static inline void
++wl_shell_surface_set_fullscreen(struct wl_shell_surface *wl_shell_surface, uint32_t method, uint32_t framerate, struct wl_output *output)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_FULLSCREEN, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, method, framerate, output);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a popup.
++ *
++ * A popup surface is a transient surface with an added pointer
++ * grab.
++ *
++ * An existing implicit grab will be changed to owner-events mode,
++ * and the popup grab will continue after the implicit grab ends
++ * (i.e. releasing the mouse button does not cause the popup to
++ * be unmapped).
++ *
++ * The popup grab continues until the window is destroyed or a
++ * mouse button is pressed in any other client's window. A click
++ * in any of the client's surfaces is reported as normal, however,
++ * clicks in other clients' surfaces will be discarded and trigger
++ * the callback.
++ *
++ * The x and y arguments specify the location of the upper left
++ * corner of the surface relative to the upper left corner of the
++ * parent surface, in surface-local coordinates.
++ */
++static inline void
++wl_shell_surface_set_popup(struct wl_shell_surface *wl_shell_surface, struct wl_seat *seat, uint32_t serial, struct wl_surface *parent, int32_t x, int32_t y, uint32_t flags)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_POPUP, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, seat, serial, parent, x, y, flags);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Map the surface as a maximized surface.
++ *
++ * If an output parameter is given then the surface will be
++ * maximized on that output. If the client does not specify the
++ * output then the compositor will apply its policy - usually
++ * choosing the output on which the surface has the biggest surface
++ * area.
++ *
++ * The compositor will reply with a configure event telling
++ * the expected new surface size. The operation is completed
++ * on the next buffer attach to this surface.
++ *
++ * A maximized surface typically fills the entire output it is
++ * bound to, except for desktop elements such as panels. This is
++ * the main difference between a maximized shell surface and a
++ * fullscreen shell surface.
++ *
++ * The details depend on the compositor implementation.
++ */
++static inline void
++wl_shell_surface_set_maximized(struct wl_shell_surface *wl_shell_surface, struct wl_output *output)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_MAXIMIZED, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, output);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Set a short title for the surface.
++ *
++ * This string may be used to identify the surface in a task bar,
++ * window list, or other user interface elements provided by the
++ * compositor.
++ *
++ * The string must be encoded in UTF-8.
++ */
++static inline void
++wl_shell_surface_set_title(struct wl_shell_surface *wl_shell_surface, const char *title)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_TITLE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, title);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ *
++ * Set a class for the surface.
++ *
++ * The surface class identifies the general class of applications
++ * to which the surface belongs. A common convention is to use the
++ * file name (or the full path if it is a non-standard location) of
++ * the application's .desktop file as the class.
++ */
++static inline void
++wl_shell_surface_set_class(struct wl_shell_surface *wl_shell_surface, const char *class_)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_shell_surface,
++                       WL_SHELL_SURFACE_SET_CLASS, NULL, wl_proxy_get_version((struct wl_proxy *) wl_shell_surface), 0, class_);
++}
++
++#ifndef WL_SURFACE_ERROR_ENUM
++#define WL_SURFACE_ERROR_ENUM
++/**
++ * @ingroup iface_wl_surface
++ * wl_surface error values
++ *
++ * These errors can be emitted in response to wl_surface requests.
++ */
++enum wl_surface_error {
++      /**
++       * buffer scale value is invalid
++       */
++      WL_SURFACE_ERROR_INVALID_SCALE = 0,
++      /**
++       * buffer transform value is invalid
++       */
++      WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
++};
++#endif /* WL_SURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_surface
++ * @struct wl_surface_listener
++ */
++struct wl_surface_listener {
++      /**
++       * surface enters an output
++       *
++       * This is emitted whenever a surface's creation, movement, or
++       * resizing results in some part of it being within the scanout
++       * region of an output.
++       *
++       * Note that a surface may be overlapping with zero or more
++       * outputs.
++       * @param output output entered by the surface
++       */
++      void (*enter)(void *data,
++                    struct wl_surface *wl_surface,
++                    struct wl_output *output);
++      /**
++       * surface leaves an output
++       *
++       * This is emitted whenever a surface's creation, movement, or
++       * resizing results in it no longer having any part of it within
++       * the scanout region of an output.
++       * @param output output left by the surface
++       */
++      void (*leave)(void *data,
++                    struct wl_surface *wl_surface,
++                    struct wl_output *output);
++};
++
++/**
++ * @ingroup iface_wl_surface
++ */
++static inline int
++wl_surface_add_listener(struct wl_surface *wl_surface,
++                      const struct wl_surface_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_surface,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_SURFACE_DESTROY 0
++#define WL_SURFACE_ATTACH 1
++#define WL_SURFACE_DAMAGE 2
++#define WL_SURFACE_FRAME 3
++#define WL_SURFACE_SET_OPAQUE_REGION 4
++#define WL_SURFACE_SET_INPUT_REGION 5
++#define WL_SURFACE_COMMIT 6
++#define WL_SURFACE_SET_BUFFER_TRANSFORM 7
++#define WL_SURFACE_SET_BUFFER_SCALE 8
++#define WL_SURFACE_DAMAGE_BUFFER 9
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_LEAVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ATTACH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_COMMIT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4
++
++/** @ingroup iface_wl_surface */
++static inline void
++wl_surface_set_user_data(struct wl_surface *wl_surface, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_surface, user_data);
++}
++
++/** @ingroup iface_wl_surface */
++static inline void *
++wl_surface_get_user_data(struct wl_surface *wl_surface)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_surface);
++}
++
++static inline uint32_t
++wl_surface_get_version(struct wl_surface *wl_surface)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_surface);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Deletes the surface and invalidates its object ID.
++ */
++static inline void
++wl_surface_destroy(struct wl_surface *wl_surface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Set a buffer as the content of this surface.
++ *
++ * The new size of the surface is calculated based on the buffer
++ * size transformed by the inverse buffer_transform and the
++ * inverse buffer_scale. This means that the supplied buffer
++ * must be an integer multiple of the buffer_scale.
++ *
++ * The x and y arguments specify the location of the new pending
++ * buffer's upper left corner, relative to the current buffer's upper
++ * left corner, in surface-local coordinates. In other words, the
++ * x and y, combined with the new surface size define in which
++ * directions the surface's size changes.
++ *
++ * Surface contents are double-buffered state, see wl_surface.commit.
++ *
++ * The initial surface contents are void; there is no content.
++ * wl_surface.attach assigns the given wl_buffer as the pending
++ * wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++ * surface contents, and the size of the surface becomes the size
++ * calculated from the wl_buffer, as described above. After commit,
++ * there is no pending buffer until the next attach.
++ *
++ * Committing a pending wl_buffer allows the compositor to read the
++ * pixels in the wl_buffer. The compositor may access the pixels at
++ * any time after the wl_surface.commit request. When the compositor
++ * will not access the pixels anymore, it will send the
++ * wl_buffer.release event. Only after receiving wl_buffer.release,
++ * the client may reuse the wl_buffer. A wl_buffer that has been
++ * attached and then replaced by another attach instead of committed
++ * will not receive a release event, and is not used by the
++ * compositor.
++ *
++ * Destroying the wl_buffer after wl_buffer.release does not change
++ * the surface contents. However, if the client destroys the
++ * wl_buffer before receiving the wl_buffer.release event, the surface
++ * contents become undefined immediately.
++ *
++ * If wl_surface.attach is sent with a NULL wl_buffer, the
++ * following wl_surface.commit will remove the surface content.
++ */
++static inline void
++wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_ATTACH, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, buffer, x, y);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in surface-local coordinates,
++ * where x and y specify the upper left corner of the damage rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage adds pending damage: the new pending damage
++ * is the union of old pending damage and the given rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * Alternatively, damage can be posted with wl_surface.damage_buffer
++ * which uses buffer coordinates instead of surface coordinates,
++ * and is probably the preferred and intuitive way of doing this.
++ */
++static inline void
++wl_surface_damage(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_DAMAGE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Request a notification when it is a good time to start drawing a new
++ * frame, by creating a frame callback. This is useful for throttling
++ * redrawing operations, and driving animations.
++ *
++ * When a client is animating on a wl_surface, it can use the 'frame'
++ * request to get notified when it is a good time to draw and commit the
++ * next frame of animation. If the client commits an update earlier than
++ * that, it is likely that some updates will not make it to the display,
++ * and the client is wasting resources by drawing too often.
++ *
++ * The frame request will take effect on the next wl_surface.commit.
++ * The notification will only be posted for one frame unless
++ * requested again. For a wl_surface, the notifications are posted in
++ * the order the frame requests were committed.
++ *
++ * The server must send the notifications so that a client
++ * will not send excessive updates, while still allowing
++ * the highest possible update rate for clients that wait for the reply
++ * before drawing again. The server should give some time for the client
++ * to draw and commit after sending the frame callback events to let it
++ * hit the next output refresh.
++ *
++ * A server should avoid signaling the frame callbacks if the
++ * surface is not visible in any way, e.g. the surface is off-screen,
++ * or completely obscured by other opaque surfaces.
++ *
++ * The object returned by this request will be destroyed by the
++ * compositor after the callback is fired and as such the client must not
++ * attempt to use it after that point.
++ *
++ * The callback_data passed in the callback is the current time, in
++ * milliseconds, with an undefined base.
++ */
++static inline struct wl_callback *
++wl_surface_frame(struct wl_surface *wl_surface)
++{
++      struct wl_proxy *callback;
++
++      callback = wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_FRAME, &wl_callback_interface, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, NULL);
++
++      return (struct wl_callback *) callback;
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets the region of the surface that contains
++ * opaque content.
++ *
++ * The opaque region is an optimization hint for the compositor
++ * that lets it optimize the redrawing of content behind opaque
++ * regions.  Setting an opaque region is not required for correct
++ * behaviour, but marking transparent content as opaque will result
++ * in repaint artifacts.
++ *
++ * The opaque region is specified in surface-local coordinates.
++ *
++ * The compositor ignores the parts of the opaque region that fall
++ * outside of the surface.
++ *
++ * Opaque region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_opaque_region changes the pending opaque region.
++ * wl_surface.commit copies the pending region to the current region.
++ * Otherwise, the pending and current regions are never changed.
++ *
++ * The initial value for an opaque region is empty. Setting the pending
++ * opaque region has copy semantics, and the wl_region object can be
++ * destroyed immediately. A NULL wl_region causes the pending opaque
++ * region to be set to empty.
++ */
++static inline void
++wl_surface_set_opaque_region(struct wl_surface *wl_surface, struct wl_region *region)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_SET_OPAQUE_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets the region of the surface that can receive
++ * pointer and touch events.
++ *
++ * Input events happening outside of this region will try the next
++ * surface in the server surface stack. The compositor ignores the
++ * parts of the input region that fall outside of the surface.
++ *
++ * The input region is specified in surface-local coordinates.
++ *
++ * Input region is double-buffered state, see wl_surface.commit.
++ *
++ * wl_surface.set_input_region changes the pending input region.
++ * wl_surface.commit copies the pending region to the current region.
++ * Otherwise the pending and current regions are never changed,
++ * except cursor and icon surfaces are special cases, see
++ * wl_pointer.set_cursor and wl_data_device.start_drag.
++ *
++ * The initial value for an input region is infinite. That means the
++ * whole surface will accept input. Setting the pending input region
++ * has copy semantics, and the wl_region object can be destroyed
++ * immediately. A NULL wl_region causes the input region to be set
++ * to infinite.
++ */
++static inline void
++wl_surface_set_input_region(struct wl_surface *wl_surface, struct wl_region *region)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_SET_INPUT_REGION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, region);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * Surface state (input, opaque, and damage regions, attached buffers,
++ * etc.) is double-buffered. Protocol requests modify the pending state,
++ * as opposed to the current state in use by the compositor. A commit
++ * request atomically applies all pending state, replacing the current
++ * state. After commit, the new pending state is as documented for each
++ * related request.
++ *
++ * On commit, a pending wl_buffer is applied first, and all other state
++ * second. This means that all coordinates in double-buffered state are
++ * relative to the new wl_buffer coming into use, except for
++ * wl_surface.attach itself. If there is no pending wl_buffer, the
++ * coordinates are relative to the current surface contents.
++ *
++ * All requests that need a commit to become effective are documented
++ * to affect double-buffered state.
++ *
++ * Other interfaces may add further double-buffered surface state.
++ */
++static inline void
++wl_surface_commit(struct wl_surface *wl_surface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_COMMIT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets an optional transformation on how the compositor
++ * interprets the contents of the buffer attached to the surface. The
++ * accepted values for the transform parameter are the values for
++ * wl_output.transform.
++ *
++ * Buffer transform is double-buffered state, see wl_surface.commit.
++ *
++ * A newly created surface has its buffer transformation set to normal.
++ *
++ * wl_surface.set_buffer_transform changes the pending buffer
++ * transformation. wl_surface.commit copies the pending buffer
++ * transformation to the current one. Otherwise, the pending and current
++ * values are never changed.
++ *
++ * The purpose of this request is to allow clients to render content
++ * according to the output transform, thus permitting the compositor to
++ * use certain optimizations even if the display is rotated. Using
++ * hardware overlays and scanning out a client buffer for fullscreen
++ * surfaces are examples of such optimizations. Those optimizations are
++ * highly dependent on the compositor implementation, so the use of this
++ * request should be considered on a case-by-case basis.
++ *
++ * Note that if the transform value includes 90 or 270 degree rotation,
++ * the width of the buffer will become the surface height and the height
++ * of the buffer will become the surface width.
++ *
++ * If transform is not one of the values from the
++ * wl_output.transform enum the invalid_transform protocol error
++ * is raised.
++ */
++static inline void
++wl_surface_set_buffer_transform(struct wl_surface *wl_surface, int32_t transform)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_SET_BUFFER_TRANSFORM, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, transform);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request sets an optional scaling factor on how the compositor
++ * interprets the contents of the buffer attached to the window.
++ *
++ * Buffer scale is double-buffered state, see wl_surface.commit.
++ *
++ * A newly created surface has its buffer scale set to 1.
++ *
++ * wl_surface.set_buffer_scale changes the pending buffer scale.
++ * wl_surface.commit copies the pending buffer scale to the current one.
++ * Otherwise, the pending and current values are never changed.
++ *
++ * The purpose of this request is to allow clients to supply higher
++ * resolution buffer data for use on high resolution outputs. It is
++ * intended that you pick the same buffer scale as the scale of the
++ * output that the surface is displayed on. This means the compositor
++ * can avoid scaling when rendering the surface on that output.
++ *
++ * Note that if the scale is larger than 1, then you have to attach
++ * a buffer that is larger (by a factor of scale in each dimension)
++ * than the desired surface size.
++ *
++ * If scale is not positive the invalid_scale protocol error is
++ * raised.
++ */
++static inline void
++wl_surface_set_buffer_scale(struct wl_surface *wl_surface, int32_t scale)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_SET_BUFFER_SCALE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, scale);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ *
++ * This request is used to describe the regions where the pending
++ * buffer is different from the current surface contents, and where
++ * the surface therefore needs to be repainted. The compositor
++ * ignores the parts of the damage that fall outside of the surface.
++ *
++ * Damage is double-buffered state, see wl_surface.commit.
++ *
++ * The damage rectangle is specified in buffer coordinates,
++ * where x and y specify the upper left corner of the damage rectangle.
++ *
++ * The initial value for pending damage is empty: no damage.
++ * wl_surface.damage_buffer adds pending damage: the new pending
++ * damage is the union of old pending damage and the given rectangle.
++ *
++ * wl_surface.commit assigns pending damage as the current damage,
++ * and clears pending damage. The server will clear the current
++ * damage as it repaints the surface.
++ *
++ * This request differs from wl_surface.damage in only one way - it
++ * takes damage in buffer coordinates instead of surface-local
++ * coordinates. While this generally is more intuitive than surface
++ * coordinates, it is especially desirable when using wp_viewport
++ * or when a drawing library (like EGL) is unaware of buffer scale
++ * and buffer transform.
++ *
++ * Note: Because buffer transformation changes and damage requests may
++ * be interleaved in the protocol stream, it is impossible to determine
++ * the actual mapping between surface and buffer damage until
++ * wl_surface.commit time. Therefore, compositors wishing to take both
++ * kinds of damage into account will have to accumulate damage from the
++ * two requests separately and only transform from one to the other
++ * after receiving the wl_surface.commit.
++ */
++static inline void
++wl_surface_damage_buffer(struct wl_surface *wl_surface, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_surface,
++                       WL_SURFACE_DAMAGE_BUFFER, NULL, wl_proxy_get_version((struct wl_proxy *) wl_surface), 0, x, y, width, height);
++}
++
++#ifndef WL_SEAT_CAPABILITY_ENUM
++#define WL_SEAT_CAPABILITY_ENUM
++/**
++ * @ingroup iface_wl_seat
++ * seat capability bitmask
++ *
++ * This is a bitmask of capabilities this seat has; if a member is
++ * set, then it is present on the seat.
++ */
++enum wl_seat_capability {
++      /**
++       * the seat has pointer devices
++       */
++      WL_SEAT_CAPABILITY_POINTER = 1,
++      /**
++       * the seat has one or more keyboards
++       */
++      WL_SEAT_CAPABILITY_KEYBOARD = 2,
++      /**
++       * the seat has touch devices
++       */
++      WL_SEAT_CAPABILITY_TOUCH = 4,
++};
++#endif /* WL_SEAT_CAPABILITY_ENUM */
++
++/**
++ * @ingroup iface_wl_seat
++ * @struct wl_seat_listener
++ */
++struct wl_seat_listener {
++      /**
++       * seat capabilities changed
++       *
++       * This is emitted whenever a seat gains or loses the pointer,
++       * keyboard or touch capabilities. The argument is a capability
++       * enum containing the complete set of capabilities this seat has.
++       *
++       * When the pointer capability is added, a client may create a
++       * wl_pointer object using the wl_seat.get_pointer request. This
++       * object will receive pointer events until the capability is
++       * removed in the future.
++       *
++       * When the pointer capability is removed, a client should destroy
++       * the wl_pointer objects associated with the seat where the
++       * capability was removed, using the wl_pointer.release request. No
++       * further pointer events will be received on these objects.
++       *
++       * In some compositors, if a seat regains the pointer capability
++       * and a client has a previously obtained wl_pointer object of
++       * version 4 or less, that object may start sending pointer events
++       * again. This behavior is considered a misinterpretation of the
++       * intended behavior and must not be relied upon by the client.
++       * wl_pointer objects of version 5 or later must not send events if
++       * created before the most recent event notifying the client of an
++       * added pointer capability.
++       *
++       * The above behavior also applies to wl_keyboard and wl_touch with
++       * the keyboard and touch capabilities, respectively.
++       * @param capabilities capabilities of the seat
++       */
++      void (*capabilities)(void *data,
++                           struct wl_seat *wl_seat,
++                           uint32_t capabilities);
++      /**
++       * unique identifier for this seat
++       *
++       * In a multiseat configuration this can be used by the client to
++       * help identify which physical devices the seat represents. Based
++       * on the seat configuration used by the compositor.
++       * @param name seat identifier
++       * @since 2
++       */
++      void (*name)(void *data,
++                   struct wl_seat *wl_seat,
++                   const char *name);
++};
++
++/**
++ * @ingroup iface_wl_seat
++ */
++static inline int
++wl_seat_add_listener(struct wl_seat *wl_seat,
++                   const struct wl_seat_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_seat,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_SEAT_GET_POINTER 0
++#define WL_SEAT_GET_KEYBOARD 1
++#define WL_SEAT_GET_TOUCH 2
++#define WL_SEAT_RELEASE 3
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_NAME_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_POINTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_RELEASE_SINCE_VERSION 5
++
++/** @ingroup iface_wl_seat */
++static inline void
++wl_seat_set_user_data(struct wl_seat *wl_seat, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_seat, user_data);
++}
++
++/** @ingroup iface_wl_seat */
++static inline void *
++wl_seat_get_user_data(struct wl_seat *wl_seat)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_seat);
++}
++
++static inline uint32_t
++wl_seat_get_version(struct wl_seat *wl_seat)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_seat);
++}
++
++/** @ingroup iface_wl_seat */
++static inline void
++wl_seat_destroy(struct wl_seat *wl_seat)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_seat);
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_pointer interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the pointer
++ * capability, or has had the pointer capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the pointer capability.
++ */
++static inline struct wl_pointer *
++wl_seat_get_pointer(struct wl_seat *wl_seat)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++                       WL_SEAT_GET_POINTER, &wl_pointer_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++      return (struct wl_pointer *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_keyboard interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the keyboard
++ * capability, or has had the keyboard capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the keyboard capability.
++ */
++static inline struct wl_keyboard *
++wl_seat_get_keyboard(struct wl_seat *wl_seat)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++                       WL_SEAT_GET_KEYBOARD, &wl_keyboard_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++      return (struct wl_keyboard *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * The ID provided will be initialized to the wl_touch interface
++ * for this seat.
++ *
++ * This request only takes effect if the seat has the touch
++ * capability, or has had the touch capability in the past.
++ * It is a protocol violation to issue this request on a seat that has
++ * never had the touch capability.
++ */
++static inline struct wl_touch *
++wl_seat_get_touch(struct wl_seat *wl_seat)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++                       WL_SEAT_GET_TOUCH, &wl_touch_interface, wl_proxy_get_version((struct wl_proxy *) wl_seat), 0, NULL);
++
++      return (struct wl_touch *) id;
++}
++
++/**
++ * @ingroup iface_wl_seat
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the seat object anymore.
++ */
++static inline void
++wl_seat_release(struct wl_seat *wl_seat)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_seat,
++                       WL_SEAT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_seat), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_POINTER_ERROR_ENUM
++#define WL_POINTER_ERROR_ENUM
++enum wl_pointer_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_POINTER_ERROR_ROLE = 0,
++};
++#endif /* WL_POINTER_ERROR_ENUM */
++
++#ifndef WL_POINTER_BUTTON_STATE_ENUM
++#define WL_POINTER_BUTTON_STATE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * physical button state
++ *
++ * Describes the physical state of a button that produced the button
++ * event.
++ */
++enum wl_pointer_button_state {
++      /**
++       * the button is not pressed
++       */
++      WL_POINTER_BUTTON_STATE_RELEASED = 0,
++      /**
++       * the button is pressed
++       */
++      WL_POINTER_BUTTON_STATE_PRESSED = 1,
++};
++#endif /* WL_POINTER_BUTTON_STATE_ENUM */
++
++#ifndef WL_POINTER_AXIS_ENUM
++#define WL_POINTER_AXIS_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis types
++ *
++ * Describes the axis types of scroll events.
++ */
++enum wl_pointer_axis {
++      /**
++       * vertical axis
++       */
++      WL_POINTER_AXIS_VERTICAL_SCROLL = 0,
++      /**
++       * horizontal axis
++       */
++      WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
++};
++#endif /* WL_POINTER_AXIS_ENUM */
++
++#ifndef WL_POINTER_AXIS_SOURCE_ENUM
++#define WL_POINTER_AXIS_SOURCE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis source types
++ *
++ * Describes the source types for axis events. This indicates to the
++ * client how an axis event was physically generated; a client may
++ * adjust the user interface accordingly. For example, scroll events
++ * from a "finger" source may be in a smooth coordinate space with
++ * kinetic scrolling whereas a "wheel" source may be in discrete steps
++ * of a number of lines.
++ */
++enum wl_pointer_axis_source {
++      /**
++       * a physical wheel rotation
++       */
++      WL_POINTER_AXIS_SOURCE_WHEEL = 0,
++      /**
++       * finger on a touch surface
++       */
++      WL_POINTER_AXIS_SOURCE_FINGER = 1,
++      /**
++       * continuous coordinate space
++       *
++       * A device generating events in a continuous coordinate space,
++       * but using something other than a finger. One example for this
++       * source is button-based scrolling where the vertical motion of a
++       * device is converted to scroll events while a button is held
++       * down.
++       */
++      WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2,
++      /**
++       * a physical wheel tilt
++       *
++       * Indicates that the actual device is a wheel but the scroll
++       * event is not caused by a rotation but a (usually sideways) tilt
++       * of the wheel.
++       * @since 6
++       */
++      WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3,
++};
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
++#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
++
++/**
++ * @ingroup iface_wl_pointer
++ * @struct wl_pointer_listener
++ */
++struct wl_pointer_listener {
++      /**
++       * enter event
++       *
++       * Notification that this seat's pointer is focused on a certain
++       * surface.
++       *
++       * When a seat's focus enters a surface, the pointer image is
++       * undefined and a client should respond to this event by setting
++       * an appropriate pointer image with the set_cursor request.
++       * @param serial serial number of the enter event
++       * @param surface surface entered by the pointer
++       * @param surface_x surface-local x coordinate
++       * @param surface_y surface-local y coordinate
++       */
++      void (*enter)(void *data,
++                    struct wl_pointer *wl_pointer,
++                    uint32_t serial,
++                    struct wl_surface *surface,
++                    wl_fixed_t surface_x,
++                    wl_fixed_t surface_y);
++      /**
++       * leave event
++       *
++       * Notification that this seat's pointer is no longer focused on
++       * a certain surface.
++       *
++       * The leave notification is sent before the enter notification for
++       * the new focus.
++       * @param serial serial number of the leave event
++       * @param surface surface left by the pointer
++       */
++      void (*leave)(void *data,
++                    struct wl_pointer *wl_pointer,
++                    uint32_t serial,
++                    struct wl_surface *surface);
++      /**
++       * pointer motion event
++       *
++       * Notification of pointer location change. The arguments
++       * surface_x and surface_y are the location relative to the focused
++       * surface.
++       * @param time timestamp with millisecond granularity
++       * @param surface_x surface-local x coordinate
++       * @param surface_y surface-local y coordinate
++       */
++      void (*motion)(void *data,
++                     struct wl_pointer *wl_pointer,
++                     uint32_t time,
++                     wl_fixed_t surface_x,
++                     wl_fixed_t surface_y);
++      /**
++       * pointer button event
++       *
++       * Mouse button click and release notifications.
++       *
++       * The location of the click is given by the last motion or enter
++       * event. The time argument is a timestamp with millisecond
++       * granularity, with an undefined base.
++       *
++       * The button is a button code as defined in the Linux kernel's
++       * linux/input-event-codes.h header file, e.g. BTN_LEFT.
++       *
++       * Any 16-bit button code value is reserved for future additions to
++       * the kernel's event code list. All other button codes above
++       * 0xFFFF are currently undefined but may be used in future
++       * versions of this protocol.
++       * @param serial serial number of the button event
++       * @param time timestamp with millisecond granularity
++       * @param button button that produced the event
++       * @param state physical state of the button
++       */
++      void (*button)(void *data,
++                     struct wl_pointer *wl_pointer,
++                     uint32_t serial,
++                     uint32_t time,
++                     uint32_t button,
++                     uint32_t state);
++      /**
++       * axis event
++       *
++       * Scroll and other axis notifications.
++       *
++       * For scroll events (vertical and horizontal scroll axes), the
++       * value parameter is the length of a vector along the specified
++       * axis in a coordinate space identical to those of motion events,
++       * representing a relative movement along the specified axis.
++       *
++       * For devices that support movements non-parallel to axes multiple
++       * axis events will be emitted.
++       *
++       * When applicable, for example for touch pads, the server can
++       * choose to emit scroll events where the motion vector is
++       * equivalent to a motion event vector.
++       *
++       * When applicable, a client can transform its content relative to
++       * the scroll distance.
++       * @param time timestamp with millisecond granularity
++       * @param axis axis type
++       * @param value length of vector in surface-local coordinate space
++       */
++      void (*axis)(void *data,
++                   struct wl_pointer *wl_pointer,
++                   uint32_t time,
++                   uint32_t axis,
++                   wl_fixed_t value);
++      /**
++       * end of a pointer event sequence
++       *
++       * Indicates the end of a set of events that logically belong
++       * together. A client is expected to accumulate the data in all
++       * events within the frame before proceeding.
++       *
++       * All wl_pointer events before a wl_pointer.frame event belong
++       * logically together. For example, in a diagonal scroll motion the
++       * compositor will send an optional wl_pointer.axis_source event,
++       * two wl_pointer.axis events (horizontal and vertical) and finally
++       * a wl_pointer.frame event. The client may use this information to
++       * calculate a diagonal vector for scrolling.
++       *
++       * When multiple wl_pointer.axis events occur within the same
++       * frame, the motion vector is the combined motion of all events.
++       * When a wl_pointer.axis and a wl_pointer.axis_stop event occur
++       * within the same frame, this indicates that axis movement in one
++       * axis has stopped but continues in the other axis. When multiple
++       * wl_pointer.axis_stop events occur within the same frame, this
++       * indicates that these axes stopped in the same instance.
++       *
++       * A wl_pointer.frame event is sent for every logical event group,
++       * even if the group only contains a single wl_pointer event.
++       * Specifically, a client may get a sequence: motion, frame,
++       * button, frame, axis, frame, axis_stop, frame.
++       *
++       * The wl_pointer.enter and wl_pointer.leave events are logical
++       * events generated by the compositor and not the hardware. These
++       * events are also grouped by a wl_pointer.frame. When a pointer
++       * moves from one surface to another, a compositor should group the
++       * wl_pointer.leave event within the same wl_pointer.frame.
++       * However, a client must not rely on wl_pointer.leave and
++       * wl_pointer.enter being in the same wl_pointer.frame.
++       * Compositor-specific policies may require the wl_pointer.leave
++       * and wl_pointer.enter event being split across multiple
++       * wl_pointer.frame groups.
++       * @since 5
++       */
++      void (*frame)(void *data,
++                    struct wl_pointer *wl_pointer);
++      /**
++       * axis source event
++       *
++       * Source information for scroll and other axes.
++       *
++       * This event does not occur on its own. It is sent before a
++       * wl_pointer.frame event and carries the source information for
++       * all events within that frame.
++       *
++       * The source specifies how this event was generated. If the source
++       * is wl_pointer.axis_source.finger, a wl_pointer.axis_stop event
++       * will be sent when the user lifts the finger off the device.
++       *
++       * If the source is wl_pointer.axis_source.wheel,
++       * wl_pointer.axis_source.wheel_tilt or
++       * wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event
++       * may or may not be sent. Whether a compositor sends an axis_stop
++       * event for these sources is hardware-specific and
++       * implementation-dependent; clients must not rely on receiving an
++       * axis_stop event for these scroll sources and should treat scroll
++       * sequences from these scroll sources as unterminated by default.
++       *
++       * This event is optional. If the source is unknown for a
++       * particular axis event sequence, no event is sent. Only one
++       * wl_pointer.axis_source event is permitted per frame.
++       *
++       * The order of wl_pointer.axis_discrete and wl_pointer.axis_source
++       * is not guaranteed.
++       * @param axis_source source of the axis event
++       * @since 5
++       */
++      void (*axis_source)(void *data,
++                          struct wl_pointer *wl_pointer,
++                          uint32_t axis_source);
++      /**
++       * axis stop event
++       *
++       * Stop notification for scroll and other axes.
++       *
++       * For some wl_pointer.axis_source types, a wl_pointer.axis_stop
++       * event is sent to notify a client that the axis sequence has
++       * terminated. This enables the client to implement kinetic
++       * scrolling. See the wl_pointer.axis_source documentation for
++       * information on when this event may be generated.
++       *
++       * Any wl_pointer.axis events with the same axis_source after this
++       * event should be considered as the start of a new axis motion.
++       *
++       * The timestamp is to be interpreted identical to the timestamp in
++       * the wl_pointer.axis event. The timestamp value may be the same
++       * as a preceding wl_pointer.axis event.
++       * @param time timestamp with millisecond granularity
++       * @param axis the axis stopped with this event
++       * @since 5
++       */
++      void (*axis_stop)(void *data,
++                        struct wl_pointer *wl_pointer,
++                        uint32_t time,
++                        uint32_t axis);
++      /**
++       * axis click event
++       *
++       * Discrete step information for scroll and other axes.
++       *
++       * This event carries the axis value of the wl_pointer.axis event
++       * in discrete steps (e.g. mouse wheel clicks).
++       *
++       * This event does not occur on its own, it is coupled with a
++       * wl_pointer.axis event that represents this axis value on a
++       * continuous scale. The protocol guarantees that each
++       * axis_discrete event is always followed by exactly one axis event
++       * with the same axis number within the same wl_pointer.frame. Note
++       * that the protocol allows for other events to occur between the
++       * axis_discrete and its coupled axis event, including other
++       * axis_discrete or axis events.
++       *
++       * This event is optional; continuous scrolling devices like
++       * two-finger scrolling on touchpads do not have discrete steps and
++       * do not generate this event.
++       *
++       * The discrete value carries the directional information. e.g. a
++       * value of -2 is two steps towards the negative direction of this
++       * axis.
++       *
++       * The axis number is identical to the axis number in the
++       * associated axis event.
++       *
++       * The order of wl_pointer.axis_discrete and wl_pointer.axis_source
++       * is not guaranteed.
++       * @param axis axis type
++       * @param discrete number of steps
++       * @since 5
++       */
++      void (*axis_discrete)(void *data,
++                            struct wl_pointer *wl_pointer,
++                            uint32_t axis,
++                            int32_t discrete);
++};
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++static inline int
++wl_pointer_add_listener(struct wl_pointer *wl_pointer,
++                      const struct wl_pointer_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_pointer,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_POINTER_SET_CURSOR 0
++#define WL_POINTER_RELEASE 1
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_BUTTON_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_FRAME_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_pointer */
++static inline void
++wl_pointer_set_user_data(struct wl_pointer *wl_pointer, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_pointer, user_data);
++}
++
++/** @ingroup iface_wl_pointer */
++static inline void *
++wl_pointer_get_user_data(struct wl_pointer *wl_pointer)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_pointer);
++}
++
++static inline uint32_t
++wl_pointer_get_version(struct wl_pointer *wl_pointer)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_pointer);
++}
++
++/** @ingroup iface_wl_pointer */
++static inline void
++wl_pointer_destroy(struct wl_pointer *wl_pointer)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_pointer);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ *
++ * Set the pointer surface, i.e., the surface that contains the
++ * pointer image (cursor). This request gives the surface the role
++ * of a cursor. If the surface already has another role, it raises
++ * a protocol error.
++ *
++ * The cursor actually changes only if the pointer
++ * focus for this device is one of the requesting client's surfaces
++ * or the surface parameter is the current pointer surface. If
++ * there was a previous surface set with this request it is
++ * replaced. If surface is NULL, the pointer image is hidden.
++ *
++ * The parameters hotspot_x and hotspot_y define the position of
++ * the pointer surface relative to the pointer location. Its
++ * top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++ * where (x, y) are the coordinates of the pointer location, in
++ * surface-local coordinates.
++ *
++ * On surface.attach requests to the pointer surface, hotspot_x
++ * and hotspot_y are decremented by the x and y parameters
++ * passed to the request. Attach must be confirmed by
++ * wl_surface.commit as usual.
++ *
++ * The hotspot can also be updated by passing the currently set
++ * pointer surface to this request with new values for hotspot_x
++ * and hotspot_y.
++ *
++ * The current and pending input regions of the wl_surface are
++ * cleared, and wl_surface.set_input_region is ignored until the
++ * wl_surface is no longer used as the cursor. When the use as a
++ * cursor ends, the current and pending input regions become
++ * undefined, and the wl_surface is unmapped.
++ */
++static inline void
++wl_pointer_set_cursor(struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *surface, int32_t hotspot_x, int32_t hotspot_y)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer,
++                       WL_POINTER_SET_CURSOR, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), 0, serial, surface, hotspot_x, hotspot_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the pointer object anymore.
++ *
++ * This request destroys the pointer proxy object, so clients must not call
++ * wl_pointer_destroy() after using this request.
++ */
++static inline void
++wl_pointer_release(struct wl_pointer *wl_pointer)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_pointer,
++                       WL_POINTER_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_pointer), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * keyboard mapping format
++ *
++ * This specifies the format of the keymap provided to the
++ * client with the wl_keyboard.keymap event.
++ */
++enum wl_keyboard_keymap_format {
++      /**
++       * no keymap; client must understand how to interpret the raw keycode
++       */
++      WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0,
++      /**
++       * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode
++       */
++      WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
++};
++#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
++
++#ifndef WL_KEYBOARD_KEY_STATE_ENUM
++#define WL_KEYBOARD_KEY_STATE_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * physical key state
++ *
++ * Describes the physical state of a key that produced the key event.
++ */
++enum wl_keyboard_key_state {
++      /**
++       * key is not pressed
++       */
++      WL_KEYBOARD_KEY_STATE_RELEASED = 0,
++      /**
++       * key is pressed
++       */
++      WL_KEYBOARD_KEY_STATE_PRESSED = 1,
++};
++#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
++
++/**
++ * @ingroup iface_wl_keyboard
++ * @struct wl_keyboard_listener
++ */
++struct wl_keyboard_listener {
++      /**
++       * keyboard mapping
++       *
++       * This event provides a file descriptor to the client which can
++       * be memory-mapped to provide a keyboard mapping description.
++       * @param format keymap format
++       * @param fd keymap file descriptor
++       * @param size keymap size, in bytes
++       */
++      void (*keymap)(void *data,
++                     struct wl_keyboard *wl_keyboard,
++                     uint32_t format,
++                     int32_t fd,
++                     uint32_t size);
++      /**
++       * enter event
++       *
++       * Notification that this seat's keyboard focus is on a certain
++       * surface.
++       * @param serial serial number of the enter event
++       * @param surface surface gaining keyboard focus
++       * @param keys the currently pressed keys
++       */
++      void (*enter)(void *data,
++                    struct wl_keyboard *wl_keyboard,
++                    uint32_t serial,
++                    struct wl_surface *surface,
++                    struct wl_array *keys);
++      /**
++       * leave event
++       *
++       * Notification that this seat's keyboard focus is no longer on a
++       * certain surface.
++       *
++       * The leave notification is sent before the enter notification for
++       * the new focus.
++       * @param serial serial number of the leave event
++       * @param surface surface that lost keyboard focus
++       */
++      void (*leave)(void *data,
++                    struct wl_keyboard *wl_keyboard,
++                    uint32_t serial,
++                    struct wl_surface *surface);
++      /**
++       * key event
++       *
++       * A key was pressed or released. The time argument is a
++       * timestamp with millisecond granularity, with an undefined base.
++       * @param serial serial number of the key event
++       * @param time timestamp with millisecond granularity
++       * @param key key that produced the event
++       * @param state physical state of the key
++       */
++      void (*key)(void *data,
++                  struct wl_keyboard *wl_keyboard,
++                  uint32_t serial,
++                  uint32_t time,
++                  uint32_t key,
++                  uint32_t state);
++      /**
++       * modifier and group state
++       *
++       * Notifies clients that the modifier and/or group state has
++       * changed, and it should update its local state.
++       * @param serial serial number of the modifiers event
++       * @param mods_depressed depressed modifiers
++       * @param mods_latched latched modifiers
++       * @param mods_locked locked modifiers
++       * @param group keyboard layout
++       */
++      void (*modifiers)(void *data,
++                        struct wl_keyboard *wl_keyboard,
++                        uint32_t serial,
++                        uint32_t mods_depressed,
++                        uint32_t mods_latched,
++                        uint32_t mods_locked,
++                        uint32_t group);
++      /**
++       * repeat rate and delay
++       *
++       * Informs the client about the keyboard's repeat rate and delay.
++       *
++       * This event is sent as soon as the wl_keyboard object has been
++       * created, and is guaranteed to be received by the client before
++       * any key press event.
++       *
++       * Negative values for either rate or delay are illegal. A rate of
++       * zero will disable any repeating (regardless of the value of
++       * delay).
++       *
++       * This event can be sent later on as well with a new value if
++       * necessary, so clients should continue listening for the event
++       * past the creation of wl_keyboard.
++       * @param rate the rate of repeating keys in characters per second
++       * @param delay delay in milliseconds since key down until repeating starts
++       * @since 4
++       */
++      void (*repeat_info)(void *data,
++                          struct wl_keyboard *wl_keyboard,
++                          int32_t rate,
++                          int32_t delay);
++};
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++static inline int
++wl_keyboard_add_listener(struct wl_keyboard *wl_keyboard,
++                       const struct wl_keyboard_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_keyboard,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_KEYBOARD_RELEASE 0
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_keyboard */
++static inline void
++wl_keyboard_set_user_data(struct wl_keyboard *wl_keyboard, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_keyboard, user_data);
++}
++
++/** @ingroup iface_wl_keyboard */
++static inline void *
++wl_keyboard_get_user_data(struct wl_keyboard *wl_keyboard)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_keyboard);
++}
++
++static inline uint32_t
++wl_keyboard_get_version(struct wl_keyboard *wl_keyboard)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_keyboard);
++}
++
++/** @ingroup iface_wl_keyboard */
++static inline void
++wl_keyboard_destroy(struct wl_keyboard *wl_keyboard)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_keyboard);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++static inline void
++wl_keyboard_release(struct wl_keyboard *wl_keyboard)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_keyboard,
++                       WL_KEYBOARD_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_keyboard), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * @struct wl_touch_listener
++ */
++struct wl_touch_listener {
++      /**
++       * touch down event and beginning of a touch sequence
++       *
++       * A new touch point has appeared on the surface. This touch
++       * point is assigned a unique ID. Future events from this touch
++       * point reference this ID. The ID ceases to be valid after a touch
++       * up event and may be reused in the future.
++       * @param serial serial number of the touch down event
++       * @param time timestamp with millisecond granularity
++       * @param surface surface touched
++       * @param id the unique ID of this touch point
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       */
++      void (*down)(void *data,
++                   struct wl_touch *wl_touch,
++                   uint32_t serial,
++                   uint32_t time,
++                   struct wl_surface *surface,
++                   int32_t id,
++                   wl_fixed_t x,
++                   wl_fixed_t y);
++      /**
++       * end of a touch event sequence
++       *
++       * The touch point has disappeared. No further events will be
++       * sent for this touch point and the touch point's ID is released
++       * and may be reused in a future touch down event.
++       * @param serial serial number of the touch up event
++       * @param time timestamp with millisecond granularity
++       * @param id the unique ID of this touch point
++       */
++      void (*up)(void *data,
++                 struct wl_touch *wl_touch,
++                 uint32_t serial,
++                 uint32_t time,
++                 int32_t id);
++      /**
++       * update of touch point coordinates
++       *
++       * A touch point has changed coordinates.
++       * @param time timestamp with millisecond granularity
++       * @param id the unique ID of this touch point
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       */
++      void (*motion)(void *data,
++                     struct wl_touch *wl_touch,
++                     uint32_t time,
++                     int32_t id,
++                     wl_fixed_t x,
++                     wl_fixed_t y);
++      /**
++       * end of touch frame event
++       *
++       * Indicates the end of a set of events that logically belong
++       * together. A client is expected to accumulate the data in all
++       * events within the frame before proceeding.
++       *
++       * A wl_touch.frame terminates at least one event but otherwise no
++       * guarantee is provided about the set of events within a frame. A
++       * client must assume that any state not updated in a frame is
++       * unchanged from the previously known state.
++       */
++      void (*frame)(void *data,
++                    struct wl_touch *wl_touch);
++      /**
++       * touch session cancelled
++       *
++       * Sent if the compositor decides the touch stream is a global
++       * gesture. No further events are sent to the clients from that
++       * particular gesture. Touch cancellation applies to all touch
++       * points currently active on this client's surface. The client is
++       * responsible for finalizing the touch points, future touch points
++       * on this surface may reuse the touch point ID.
++       */
++      void (*cancel)(void *data,
++                     struct wl_touch *wl_touch);
++      /**
++       * update shape of touch point
++       *
++       * Sent when a touchpoint has changed its shape.
++       *
++       * This event does not occur on its own. It is sent before a
++       * wl_touch.frame event and carries the new shape information for
++       * any previously reported, or new touch points of that frame.
++       *
++       * Other events describing the touch point such as wl_touch.down,
++       * wl_touch.motion or wl_touch.orientation may be sent within the
++       * same wl_touch.frame. A client should treat these events as a
++       * single logical touch point update. The order of wl_touch.shape,
++       * wl_touch.orientation and wl_touch.motion is not guaranteed. A
++       * wl_touch.down event is guaranteed to occur before the first
++       * wl_touch.shape event for this touch ID but both events may occur
++       * within the same wl_touch.frame.
++       *
++       * A touchpoint shape is approximated by an ellipse through the
++       * major and minor axis length. The major axis length describes the
++       * longer diameter of the ellipse, while the minor axis length
++       * describes the shorter diameter. Major and minor are orthogonal
++       * and both are specified in surface-local coordinates. The center
++       * of the ellipse is always at the touchpoint location as reported
++       * by wl_touch.down or wl_touch.move.
++       *
++       * This event is only sent by the compositor if the touch device
++       * supports shape reports. The client has to make reasonable
++       * assumptions about the shape if it did not receive this event.
++       * @param id the unique ID of this touch point
++       * @param major length of the major axis in surface-local coordinates
++       * @param minor length of the minor axis in surface-local coordinates
++       * @since 6
++       */
++      void (*shape)(void *data,
++                    struct wl_touch *wl_touch,
++                    int32_t id,
++                    wl_fixed_t major,
++                    wl_fixed_t minor);
++      /**
++       * update orientation of touch point
++       *
++       * Sent when a touchpoint has changed its orientation.
++       *
++       * This event does not occur on its own. It is sent before a
++       * wl_touch.frame event and carries the new shape information for
++       * any previously reported, or new touch points of that frame.
++       *
++       * Other events describing the touch point such as wl_touch.down,
++       * wl_touch.motion or wl_touch.shape may be sent within the same
++       * wl_touch.frame. A client should treat these events as a single
++       * logical touch point update. The order of wl_touch.shape,
++       * wl_touch.orientation and wl_touch.motion is not guaranteed. A
++       * wl_touch.down event is guaranteed to occur before the first
++       * wl_touch.orientation event for this touch ID but both events may
++       * occur within the same wl_touch.frame.
++       *
++       * The orientation describes the clockwise angle of a touchpoint's
++       * major axis to the positive surface y-axis and is normalized to
++       * the -180 to +180 degree range. The granularity of orientation
++       * depends on the touch device, some devices only support binary
++       * rotation values between 0 and 90 degrees.
++       *
++       * This event is only sent by the compositor if the touch device
++       * supports orientation reports.
++       * @param id the unique ID of this touch point
++       * @param orientation angle between major axis and positive surface y-axis in degrees
++       * @since 6
++       */
++      void (*orientation)(void *data,
++                          struct wl_touch *wl_touch,
++                          int32_t id,
++                          wl_fixed_t orientation);
++};
++
++/**
++ * @ingroup iface_wl_touch
++ */
++static inline int
++wl_touch_add_listener(struct wl_touch *wl_touch,
++                    const struct wl_touch_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_touch,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_TOUCH_RELEASE 0
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_DOWN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_UP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_CANCEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_SHAPE_SINCE_VERSION 6
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_touch */
++static inline void
++wl_touch_set_user_data(struct wl_touch *wl_touch, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_touch, user_data);
++}
++
++/** @ingroup iface_wl_touch */
++static inline void *
++wl_touch_get_user_data(struct wl_touch *wl_touch)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_touch);
++}
++
++static inline uint32_t
++wl_touch_get_version(struct wl_touch *wl_touch)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_touch);
++}
++
++/** @ingroup iface_wl_touch */
++static inline void
++wl_touch_destroy(struct wl_touch *wl_touch)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_touch);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ */
++static inline void
++wl_touch_release(struct wl_touch *wl_touch)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_touch,
++                       WL_TOUCH_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_touch), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifndef WL_OUTPUT_SUBPIXEL_ENUM
++#define WL_OUTPUT_SUBPIXEL_ENUM
++/**
++ * @ingroup iface_wl_output
++ * subpixel geometry information
++ *
++ * This enumeration describes how the physical
++ * pixels on an output are laid out.
++ */
++enum wl_output_subpixel {
++      /**
++       * unknown geometry
++       */
++      WL_OUTPUT_SUBPIXEL_UNKNOWN = 0,
++      /**
++       * no geometry
++       */
++      WL_OUTPUT_SUBPIXEL_NONE = 1,
++      /**
++       * horizontal RGB
++       */
++      WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2,
++      /**
++       * horizontal BGR
++       */
++      WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3,
++      /**
++       * vertical RGB
++       */
++      WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4,
++      /**
++       * vertical BGR
++       */
++      WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
++};
++#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
++
++#ifndef WL_OUTPUT_TRANSFORM_ENUM
++#define WL_OUTPUT_TRANSFORM_ENUM
++/**
++ * @ingroup iface_wl_output
++ * transform from framebuffer to output
++ *
++ * This describes the transform that a compositor will apply to a
++ * surface to compensate for the rotation or mirroring of an
++ * output device.
++ *
++ * The flipped values correspond to an initial flip around a
++ * vertical axis followed by rotation.
++ *
++ * The purpose is mainly to allow clients to render accordingly and
++ * tell the compositor, so that for fullscreen surfaces, the
++ * compositor will still be able to scan out directly from client
++ * surfaces.
++ */
++enum wl_output_transform {
++      /**
++       * no transform
++       */
++      WL_OUTPUT_TRANSFORM_NORMAL = 0,
++      /**
++       * 90 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_90 = 1,
++      /**
++       * 180 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_180 = 2,
++      /**
++       * 270 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_270 = 3,
++      /**
++       * 180 degree flip around a vertical axis
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED = 4,
++      /**
++       * flip and rotate 90 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5,
++      /**
++       * flip and rotate 180 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6,
++      /**
++       * flip and rotate 270 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
++};
++#endif /* WL_OUTPUT_TRANSFORM_ENUM */
++
++#ifndef WL_OUTPUT_MODE_ENUM
++#define WL_OUTPUT_MODE_ENUM
++/**
++ * @ingroup iface_wl_output
++ * mode information
++ *
++ * These flags describe properties of an output mode.
++ * They are used in the flags bitfield of the mode event.
++ */
++enum wl_output_mode {
++      /**
++       * indicates this is the current mode
++       */
++      WL_OUTPUT_MODE_CURRENT = 0x1,
++      /**
++       * indicates this is the preferred mode
++       */
++      WL_OUTPUT_MODE_PREFERRED = 0x2,
++};
++#endif /* WL_OUTPUT_MODE_ENUM */
++
++/**
++ * @ingroup iface_wl_output
++ * @struct wl_output_listener
++ */
++struct wl_output_listener {
++      /**
++       * properties of the output
++       *
++       * The geometry event describes geometric properties of the
++       * output. The event is sent when binding to the output object and
++       * whenever any of the properties change.
++       * @param x x position within the global compositor space
++       * @param y y position within the global compositor space
++       * @param physical_width width in millimeters of the output
++       * @param physical_height height in millimeters of the output
++       * @param subpixel subpixel orientation of the output
++       * @param make textual description of the manufacturer
++       * @param model textual description of the model
++       * @param transform transform that maps framebuffer to output
++       */
++      void (*geometry)(void *data,
++                       struct wl_output *wl_output,
++                       int32_t x,
++                       int32_t y,
++                       int32_t physical_width,
++                       int32_t physical_height,
++                       int32_t subpixel,
++                       const char *make,
++                       const char *model,
++                       int32_t transform);
++      /**
++       * advertise available modes for the output
++       *
++       * The mode event describes an available mode for the output.
++       *
++       * The event is sent when binding to the output object and there
++       * will always be one mode, the current mode. The event is sent
++       * again if an output changes mode, for the mode that is now
++       * current. In other words, the current mode is always the last
++       * mode that was received with the current flag set.
++       *
++       * The size of a mode is given in physical hardware units of the
++       * output device. This is not necessarily the same as the output
++       * size in the global compositor space. For instance, the output
++       * may be scaled, as described in wl_output.scale, or transformed,
++       * as described in wl_output.transform.
++       * @param flags bitfield of mode flags
++       * @param width width of the mode in hardware units
++       * @param height height of the mode in hardware units
++       * @param refresh vertical refresh rate in mHz
++       */
++      void (*mode)(void *data,
++                   struct wl_output *wl_output,
++                   uint32_t flags,
++                   int32_t width,
++                   int32_t height,
++                   int32_t refresh);
++      /**
++       * sent all information about output
++       *
++       * This event is sent after all other properties have been sent
++       * after binding to the output object and after any other property
++       * changes done after that. This allows changes to the output
++       * properties to be seen as atomic, even if they happen via
++       * multiple events.
++       * @since 2
++       */
++      void (*done)(void *data,
++                   struct wl_output *wl_output);
++      /**
++       * output scaling properties
++       *
++       * This event contains scaling geometry information that is not
++       * in the geometry event. It may be sent after binding the output
++       * object or if the output scale changes later. If it is not sent,
++       * the client should assume a scale of 1.
++       *
++       * A scale larger than 1 means that the compositor will
++       * automatically scale surface buffers by this amount when
++       * rendering. This is used for very high resolution displays where
++       * applications rendering at the native resolution would be too
++       * small to be legible.
++       *
++       * It is intended that scaling aware clients track the current
++       * output of a surface, and if it is on a scaled output it should
++       * use wl_surface.set_buffer_scale with the scale of the output.
++       * That way the compositor can avoid scaling the surface, and the
++       * client can supply a higher detail image.
++       * @param factor scaling factor of output
++       * @since 2
++       */
++      void (*scale)(void *data,
++                    struct wl_output *wl_output,
++                    int32_t factor);
++};
++
++/**
++ * @ingroup iface_wl_output
++ */
++static inline int
++wl_output_add_listener(struct wl_output *wl_output,
++                     const struct wl_output_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) wl_output,
++                                   (void (**)(void)) listener, data);
++}
++
++#define WL_OUTPUT_RELEASE 0
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_MODE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_DONE_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_SCALE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_RELEASE_SINCE_VERSION 3
++
++/** @ingroup iface_wl_output */
++static inline void
++wl_output_set_user_data(struct wl_output *wl_output, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_output, user_data);
++}
++
++/** @ingroup iface_wl_output */
++static inline void *
++wl_output_get_user_data(struct wl_output *wl_output)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_output);
++}
++
++static inline uint32_t
++wl_output_get_version(struct wl_output *wl_output)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_output);
++}
++
++/** @ingroup iface_wl_output */
++static inline void
++wl_output_destroy(struct wl_output *wl_output)
++{
++      wl_proxy_destroy((struct wl_proxy *) wl_output);
++}
++
++/**
++ * @ingroup iface_wl_output
++ *
++ * Using this request a client can tell the server that it is not going to
++ * use the output object anymore.
++ */
++static inline void
++wl_output_release(struct wl_output *wl_output)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_output,
++                       WL_OUTPUT_RELEASE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_output), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#define WL_REGION_DESTROY 0
++#define WL_REGION_ADD 1
++#define WL_REGION_SUBTRACT 2
++
++
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_ADD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_SUBTRACT_SINCE_VERSION 1
++
++/** @ingroup iface_wl_region */
++static inline void
++wl_region_set_user_data(struct wl_region *wl_region, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_region, user_data);
++}
++
++/** @ingroup iface_wl_region */
++static inline void *
++wl_region_get_user_data(struct wl_region *wl_region)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_region);
++}
++
++static inline uint32_t
++wl_region_get_version(struct wl_region *wl_region)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_region);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Destroy the region.  This will invalidate the object ID.
++ */
++static inline void
++wl_region_destroy(struct wl_region *wl_region)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++                       WL_REGION_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Add the specified rectangle to the region.
++ */
++static inline void
++wl_region_add(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++                       WL_REGION_ADD, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height);
++}
++
++/**
++ * @ingroup iface_wl_region
++ *
++ * Subtract the specified rectangle from the region.
++ */
++static inline void
++wl_region_subtract(struct wl_region *wl_region, int32_t x, int32_t y, int32_t width, int32_t height)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_region,
++                       WL_REGION_SUBTRACT, NULL, wl_proxy_get_version((struct wl_proxy *) wl_region), 0, x, y, width, height);
++}
++
++#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM
++#define WL_SUBCOMPOSITOR_ERROR_ENUM
++enum wl_subcompositor_error {
++      /**
++       * the to-be sub-surface is invalid
++       */
++      WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
++
++#define WL_SUBCOMPOSITOR_DESTROY 0
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE 1
++
++
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1
++
++/** @ingroup iface_wl_subcompositor */
++static inline void
++wl_subcompositor_set_user_data(struct wl_subcompositor *wl_subcompositor, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_subcompositor, user_data);
++}
++
++/** @ingroup iface_wl_subcompositor */
++static inline void *
++wl_subcompositor_get_user_data(struct wl_subcompositor *wl_subcompositor)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_subcompositor);
++}
++
++static inline uint32_t
++wl_subcompositor_get_version(struct wl_subcompositor *wl_subcompositor)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_subcompositor);
++}
++
++/**
++ * @ingroup iface_wl_subcompositor
++ *
++ * Informs the server that the client will not be using this
++ * protocol object anymore. This does not affect any other
++ * objects, wl_subsurface objects included.
++ */
++static inline void
++wl_subcompositor_destroy(struct wl_subcompositor *wl_subcompositor)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor,
++                       WL_SUBCOMPOSITOR_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_subcompositor
++ *
++ * Create a sub-surface interface for the given surface, and
++ * associate it with the given parent surface. This turns a
++ * plain wl_surface into a sub-surface.
++ *
++ * The to-be sub-surface must not already have another role, and it
++ * must not have an existing wl_subsurface object. Otherwise a protocol
++ * error is raised.
++ */
++static inline struct wl_subsurface *
++wl_subcompositor_get_subsurface(struct wl_subcompositor *wl_subcompositor, struct wl_surface *surface, struct wl_surface *parent)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_flags((struct wl_proxy *) wl_subcompositor,
++                       WL_SUBCOMPOSITOR_GET_SUBSURFACE, &wl_subsurface_interface, wl_proxy_get_version((struct wl_proxy *) wl_subcompositor), 0, NULL, surface, parent);
++
++      return (struct wl_subsurface *) id;
++}
++
++#ifndef WL_SUBSURFACE_ERROR_ENUM
++#define WL_SUBSURFACE_ERROR_ENUM
++enum wl_subsurface_error {
++      /**
++       * wl_surface is not a sibling or the parent
++       */
++      WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBSURFACE_ERROR_ENUM */
++
++#define WL_SUBSURFACE_DESTROY 0
++#define WL_SUBSURFACE_SET_POSITION 1
++#define WL_SUBSURFACE_PLACE_ABOVE 2
++#define WL_SUBSURFACE_PLACE_BELOW 3
++#define WL_SUBSURFACE_SET_SYNC 4
++#define WL_SUBSURFACE_SET_DESYNC 5
++
++
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1
++
++/** @ingroup iface_wl_subsurface */
++static inline void
++wl_subsurface_set_user_data(struct wl_subsurface *wl_subsurface, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) wl_subsurface, user_data);
++}
++
++/** @ingroup iface_wl_subsurface */
++static inline void *
++wl_subsurface_get_user_data(struct wl_subsurface *wl_subsurface)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) wl_subsurface);
++}
++
++static inline uint32_t
++wl_subsurface_get_version(struct wl_subsurface *wl_subsurface)
++{
++      return wl_proxy_get_version((struct wl_proxy *) wl_subsurface);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * The sub-surface interface is removed from the wl_surface object
++ * that was turned into a sub-surface with a
++ * wl_subcompositor.get_subsurface request. The wl_surface's association
++ * to the parent is deleted, and the wl_surface loses its role as
++ * a sub-surface. The wl_surface is unmapped.
++ */
++static inline void
++wl_subsurface_destroy(struct wl_subsurface *wl_subsurface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), WL_MARSHAL_FLAG_DESTROY);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * This schedules a sub-surface position change.
++ * The sub-surface will be moved so that its origin (top left
++ * corner pixel) will be at the location x, y of the parent surface
++ * coordinate system. The coordinates are not restricted to the parent
++ * surface area. Negative values are allowed.
++ *
++ * The scheduled coordinates will take effect whenever the state of the
++ * parent surface is applied. When this happens depends on whether the
++ * parent surface is in synchronized mode or not. See
++ * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++ *
++ * If more than one set_position request is invoked by the client before
++ * the commit of the parent surface, the position of a new request always
++ * replaces the scheduled position from any previous request.
++ *
++ * The initial position is 0, 0.
++ */
++static inline void
++wl_subsurface_set_position(struct wl_subsurface *wl_subsurface, int32_t x, int32_t y)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_SET_POSITION, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, x, y);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * This sub-surface is taken from the stack, and put back just
++ * above the reference surface, changing the z-order of the sub-surfaces.
++ * The reference surface must be one of the sibling surfaces, or the
++ * parent surface. Using any other surface, including this sub-surface,
++ * will cause a protocol error.
++ *
++ * The z-order is double-buffered. Requests are handled in order and
++ * applied immediately to a pending state. The final pending state is
++ * copied to the active state the next time the state of the parent
++ * surface is applied. When this happens depends on whether the parent
++ * surface is in synchronized mode or not. See wl_subsurface.set_sync and
++ * wl_subsurface.set_desync for details.
++ *
++ * A new sub-surface is initially added as the top-most in the stack
++ * of its siblings and parent.
++ */
++static inline void
++wl_subsurface_place_above(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_PLACE_ABOVE, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * The sub-surface is placed just below the reference surface.
++ * See wl_subsurface.place_above.
++ */
++static inline void
++wl_subsurface_place_below(struct wl_subsurface *wl_subsurface, struct wl_surface *sibling)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_PLACE_BELOW, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0, sibling);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * Change the commit behaviour of the sub-surface to synchronized
++ * mode, also described as the parent dependent mode.
++ *
++ * In synchronized mode, wl_surface.commit on a sub-surface will
++ * accumulate the committed state in a cache, but the state will
++ * not be applied and hence will not change the compositor output.
++ * The cached state is applied to the sub-surface immediately after
++ * the parent surface's state is applied. This ensures atomic
++ * updates of the parent and all its synchronized sub-surfaces.
++ * Applying the cached state will invalidate the cache, so further
++ * parent surface commits do not (re-)apply old state.
++ *
++ * See wl_subsurface for the recursive effect of this mode.
++ */
++static inline void
++wl_subsurface_set_sync(struct wl_subsurface *wl_subsurface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_SET_SYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
++}
++
++/**
++ * @ingroup iface_wl_subsurface
++ *
++ * Change the commit behaviour of the sub-surface to desynchronized
++ * mode, also described as independent or freely running mode.
++ *
++ * In desynchronized mode, wl_surface.commit on a sub-surface will
++ * apply the pending state directly, without caching, as happens
++ * normally with a wl_surface. Calling wl_surface.commit on the
++ * parent surface has no effect on the sub-surface's wl_surface
++ * state. This mode allows a sub-surface to be updated on its own.
++ *
++ * If cached state exists when wl_surface.commit is called in
++ * desynchronized mode, the pending state is added to the cached
++ * state, and applied as a whole. This invalidates the cache.
++ *
++ * Note: even if a sub-surface is set to desynchronized, a parent
++ * sub-surface may override it to behave as synchronized. For details,
++ * see wl_subsurface.
++ *
++ * If a surface's parent surface behaves as desynchronized, then
++ * the cached state is applied on set_desync.
++ */
++static inline void
++wl_subsurface_set_desync(struct wl_subsurface *wl_subsurface)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) wl_subsurface,
++                       WL_SUBSURFACE_SET_DESYNC, NULL, wl_proxy_get_version((struct wl_proxy *) wl_subsurface), 0);
++}
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2055c88ebfbed535bc5c30352fa0c192b943dc06
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,507 @@@
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface wl_buffer_interface;
++extern const struct wl_interface wl_callback_interface;
++extern const struct wl_interface wl_data_device_interface;
++extern const struct wl_interface wl_data_offer_interface;
++extern const struct wl_interface wl_data_source_interface;
++extern const struct wl_interface wl_keyboard_interface;
++extern const struct wl_interface wl_output_interface;
++extern const struct wl_interface wl_pointer_interface;
++extern const struct wl_interface wl_region_interface;
++extern const struct wl_interface wl_registry_interface;
++extern const struct wl_interface wl_seat_interface;
++extern const struct wl_interface wl_shell_surface_interface;
++extern const struct wl_interface wl_shm_pool_interface;
++extern const struct wl_interface wl_subsurface_interface;
++extern const struct wl_interface wl_surface_interface;
++extern const struct wl_interface wl_touch_interface;
++
++static const struct wl_interface *wayland_types[] = {
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &wl_callback_interface,
++      &wl_registry_interface,
++      &wl_surface_interface,
++      &wl_region_interface,
++      &wl_buffer_interface,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &wl_shm_pool_interface,
++      NULL,
++      NULL,
++      &wl_data_source_interface,
++      &wl_surface_interface,
++      &wl_surface_interface,
++      NULL,
++      &wl_data_source_interface,
++      NULL,
++      &wl_data_offer_interface,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      &wl_data_offer_interface,
++      &wl_data_offer_interface,
++      &wl_data_source_interface,
++      &wl_data_device_interface,
++      &wl_seat_interface,
++      &wl_shell_surface_interface,
++      &wl_surface_interface,
++      &wl_seat_interface,
++      NULL,
++      &wl_seat_interface,
++      NULL,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &wl_output_interface,
++      &wl_seat_interface,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      NULL,
++      &wl_output_interface,
++      &wl_buffer_interface,
++      NULL,
++      NULL,
++      &wl_callback_interface,
++      &wl_region_interface,
++      &wl_region_interface,
++      &wl_output_interface,
++      &wl_output_interface,
++      &wl_pointer_interface,
++      &wl_keyboard_interface,
++      &wl_touch_interface,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      &wl_surface_interface,
++      NULL,
++      NULL,
++      NULL,
++      &wl_subsurface_interface,
++      &wl_surface_interface,
++      &wl_surface_interface,
++      &wl_surface_interface,
++      &wl_surface_interface,
++};
++
++static const struct wl_message wl_display_requests[] = {
++      { "sync", "n", wayland_types + 8 },
++      { "get_registry", "n", wayland_types + 9 },
++};
++
++static const struct wl_message wl_display_events[] = {
++      { "error", "ous", wayland_types + 0 },
++      { "delete_id", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_display_interface = {
++      "wl_display", 1,
++      2, wl_display_requests,
++      2, wl_display_events,
++};
++
++static const struct wl_message wl_registry_requests[] = {
++      { "bind", "usun", wayland_types + 0 },
++};
++
++static const struct wl_message wl_registry_events[] = {
++      { "global", "usu", wayland_types + 0 },
++      { "global_remove", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_registry_interface = {
++      "wl_registry", 1,
++      1, wl_registry_requests,
++      2, wl_registry_events,
++};
++
++static const struct wl_message wl_callback_events[] = {
++      { "done", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_callback_interface = {
++      "wl_callback", 1,
++      0, NULL,
++      1, wl_callback_events,
++};
++
++static const struct wl_message wl_compositor_requests[] = {
++      { "create_surface", "n", wayland_types + 10 },
++      { "create_region", "n", wayland_types + 11 },
++};
++
++WL_EXPORT const struct wl_interface wl_compositor_interface = {
++      "wl_compositor", 4,
++      2, wl_compositor_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_shm_pool_requests[] = {
++      { "create_buffer", "niiiiu", wayland_types + 12 },
++      { "destroy", "", wayland_types + 0 },
++      { "resize", "i", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shm_pool_interface = {
++      "wl_shm_pool", 1,
++      3, wl_shm_pool_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_shm_requests[] = {
++      { "create_pool", "nhi", wayland_types + 18 },
++};
++
++static const struct wl_message wl_shm_events[] = {
++      { "format", "u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shm_interface = {
++      "wl_shm", 1,
++      1, wl_shm_requests,
++      1, wl_shm_events,
++};
++
++static const struct wl_message wl_buffer_requests[] = {
++      { "destroy", "", wayland_types + 0 },
++};
++
++static const struct wl_message wl_buffer_events[] = {
++      { "release", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_buffer_interface = {
++      "wl_buffer", 1,
++      1, wl_buffer_requests,
++      1, wl_buffer_events,
++};
++
++static const struct wl_message wl_data_offer_requests[] = {
++      { "accept", "u?s", wayland_types + 0 },
++      { "receive", "sh", wayland_types + 0 },
++      { "destroy", "", wayland_types + 0 },
++      { "finish", "3", wayland_types + 0 },
++      { "set_actions", "3uu", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_offer_events[] = {
++      { "offer", "s", wayland_types + 0 },
++      { "source_actions", "3u", wayland_types + 0 },
++      { "action", "3u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_offer_interface = {
++      "wl_data_offer", 3,
++      5, wl_data_offer_requests,
++      3, wl_data_offer_events,
++};
++
++static const struct wl_message wl_data_source_requests[] = {
++      { "offer", "s", wayland_types + 0 },
++      { "destroy", "", wayland_types + 0 },
++      { "set_actions", "3u", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_source_events[] = {
++      { "target", "?s", wayland_types + 0 },
++      { "send", "sh", wayland_types + 0 },
++      { "cancelled", "", wayland_types + 0 },
++      { "dnd_drop_performed", "3", wayland_types + 0 },
++      { "dnd_finished", "3", wayland_types + 0 },
++      { "action", "3u", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_source_interface = {
++      "wl_data_source", 3,
++      3, wl_data_source_requests,
++      6, wl_data_source_events,
++};
++
++static const struct wl_message wl_data_device_requests[] = {
++      { "start_drag", "?oo?ou", wayland_types + 21 },
++      { "set_selection", "?ou", wayland_types + 25 },
++      { "release", "2", wayland_types + 0 },
++};
++
++static const struct wl_message wl_data_device_events[] = {
++      { "data_offer", "n", wayland_types + 27 },
++      { "enter", "uoff?o", wayland_types + 28 },
++      { "leave", "", wayland_types + 0 },
++      { "motion", "uff", wayland_types + 0 },
++      { "drop", "", wayland_types + 0 },
++      { "selection", "?o", wayland_types + 33 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_device_interface = {
++      "wl_data_device", 3,
++      3, wl_data_device_requests,
++      6, wl_data_device_events,
++};
++
++static const struct wl_message wl_data_device_manager_requests[] = {
++      { "create_data_source", "n", wayland_types + 34 },
++      { "get_data_device", "no", wayland_types + 35 },
++};
++
++WL_EXPORT const struct wl_interface wl_data_device_manager_interface = {
++      "wl_data_device_manager", 3,
++      2, wl_data_device_manager_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_shell_requests[] = {
++      { "get_shell_surface", "no", wayland_types + 37 },
++};
++
++WL_EXPORT const struct wl_interface wl_shell_interface = {
++      "wl_shell", 1,
++      1, wl_shell_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_shell_surface_requests[] = {
++      { "pong", "u", wayland_types + 0 },
++      { "move", "ou", wayland_types + 39 },
++      { "resize", "ouu", wayland_types + 41 },
++      { "set_toplevel", "", wayland_types + 0 },
++      { "set_transient", "oiiu", wayland_types + 44 },
++      { "set_fullscreen", "uu?o", wayland_types + 48 },
++      { "set_popup", "ouoiiu", wayland_types + 51 },
++      { "set_maximized", "?o", wayland_types + 57 },
++      { "set_title", "s", wayland_types + 0 },
++      { "set_class", "s", wayland_types + 0 },
++};
++
++static const struct wl_message wl_shell_surface_events[] = {
++      { "ping", "u", wayland_types + 0 },
++      { "configure", "uii", wayland_types + 0 },
++      { "popup_done", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_shell_surface_interface = {
++      "wl_shell_surface", 1,
++      10, wl_shell_surface_requests,
++      3, wl_shell_surface_events,
++};
++
++static const struct wl_message wl_surface_requests[] = {
++      { "destroy", "", wayland_types + 0 },
++      { "attach", "?oii", wayland_types + 58 },
++      { "damage", "iiii", wayland_types + 0 },
++      { "frame", "n", wayland_types + 61 },
++      { "set_opaque_region", "?o", wayland_types + 62 },
++      { "set_input_region", "?o", wayland_types + 63 },
++      { "commit", "", wayland_types + 0 },
++      { "set_buffer_transform", "2i", wayland_types + 0 },
++      { "set_buffer_scale", "3i", wayland_types + 0 },
++      { "damage_buffer", "4iiii", wayland_types + 0 },
++};
++
++static const struct wl_message wl_surface_events[] = {
++      { "enter", "o", wayland_types + 64 },
++      { "leave", "o", wayland_types + 65 },
++};
++
++WL_EXPORT const struct wl_interface wl_surface_interface = {
++      "wl_surface", 4,
++      10, wl_surface_requests,
++      2, wl_surface_events,
++};
++
++static const struct wl_message wl_seat_requests[] = {
++      { "get_pointer", "n", wayland_types + 66 },
++      { "get_keyboard", "n", wayland_types + 67 },
++      { "get_touch", "n", wayland_types + 68 },
++      { "release", "5", wayland_types + 0 },
++};
++
++static const struct wl_message wl_seat_events[] = {
++      { "capabilities", "u", wayland_types + 0 },
++      { "name", "2s", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_seat_interface = {
++      "wl_seat", 6,
++      4, wl_seat_requests,
++      2, wl_seat_events,
++};
++
++static const struct wl_message wl_pointer_requests[] = {
++      { "set_cursor", "u?oii", wayland_types + 69 },
++      { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_pointer_events[] = {
++      { "enter", "uoff", wayland_types + 73 },
++      { "leave", "uo", wayland_types + 77 },
++      { "motion", "uff", wayland_types + 0 },
++      { "button", "uuuu", wayland_types + 0 },
++      { "axis", "uuf", wayland_types + 0 },
++      { "frame", "5", wayland_types + 0 },
++      { "axis_source", "5u", wayland_types + 0 },
++      { "axis_stop", "5uu", wayland_types + 0 },
++      { "axis_discrete", "5ui", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_pointer_interface = {
++      "wl_pointer", 6,
++      2, wl_pointer_requests,
++      9, wl_pointer_events,
++};
++
++static const struct wl_message wl_keyboard_requests[] = {
++      { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_keyboard_events[] = {
++      { "keymap", "uhu", wayland_types + 0 },
++      { "enter", "uoa", wayland_types + 79 },
++      { "leave", "uo", wayland_types + 82 },
++      { "key", "uuuu", wayland_types + 0 },
++      { "modifiers", "uuuuu", wayland_types + 0 },
++      { "repeat_info", "4ii", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_keyboard_interface = {
++      "wl_keyboard", 6,
++      1, wl_keyboard_requests,
++      6, wl_keyboard_events,
++};
++
++static const struct wl_message wl_touch_requests[] = {
++      { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_touch_events[] = {
++      { "down", "uuoiff", wayland_types + 84 },
++      { "up", "uui", wayland_types + 0 },
++      { "motion", "uiff", wayland_types + 0 },
++      { "frame", "", wayland_types + 0 },
++      { "cancel", "", wayland_types + 0 },
++      { "shape", "6iff", wayland_types + 0 },
++      { "orientation", "6if", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_touch_interface = {
++      "wl_touch", 6,
++      1, wl_touch_requests,
++      7, wl_touch_events,
++};
++
++static const struct wl_message wl_output_requests[] = {
++      { "release", "3", wayland_types + 0 },
++};
++
++static const struct wl_message wl_output_events[] = {
++      { "geometry", "iiiiissi", wayland_types + 0 },
++      { "mode", "uiii", wayland_types + 0 },
++      { "done", "2", wayland_types + 0 },
++      { "scale", "2i", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_output_interface = {
++      "wl_output", 3,
++      1, wl_output_requests,
++      4, wl_output_events,
++};
++
++static const struct wl_message wl_region_requests[] = {
++      { "destroy", "", wayland_types + 0 },
++      { "add", "iiii", wayland_types + 0 },
++      { "subtract", "iiii", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_region_interface = {
++      "wl_region", 1,
++      3, wl_region_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_subcompositor_requests[] = {
++      { "destroy", "", wayland_types + 0 },
++      { "get_subsurface", "noo", wayland_types + 90 },
++};
++
++WL_EXPORT const struct wl_interface wl_subcompositor_interface = {
++      "wl_subcompositor", 1,
++      2, wl_subcompositor_requests,
++      0, NULL,
++};
++
++static const struct wl_message wl_subsurface_requests[] = {
++      { "destroy", "", wayland_types + 0 },
++      { "set_position", "ii", wayland_types + 0 },
++      { "place_above", "o", wayland_types + 93 },
++      { "place_below", "o", wayland_types + 94 },
++      { "set_sync", "", wayland_types + 0 },
++      { "set_desync", "", wayland_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface wl_subsurface_interface = {
++      "wl_subsurface", 1,
++      6, wl_subsurface_requests,
++      0, NULL,
++};
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7cfa4e7aa4549688b8f2754ddbd617f7132ae92b
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4401 @@@
++/* SCANNER TEST */
++
++#ifndef WAYLAND_SERVER_PROTOCOL_H
++#define WAYLAND_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_wayland The wayland protocol
++ * @section page_ifaces_wayland Interfaces
++ * - @subpage page_iface_wl_display - core global object
++ * - @subpage page_iface_wl_registry - global registry object
++ * - @subpage page_iface_wl_callback - callback object
++ * - @subpage page_iface_wl_compositor - the compositor singleton
++ * - @subpage page_iface_wl_shm_pool - a shared memory pool
++ * - @subpage page_iface_wl_shm - shared memory support
++ * - @subpage page_iface_wl_buffer - content for a wl_surface
++ * - @subpage page_iface_wl_data_offer - offer to transfer data
++ * - @subpage page_iface_wl_data_source - offer to transfer data
++ * - @subpage page_iface_wl_data_device - data transfer device
++ * - @subpage page_iface_wl_data_device_manager - data transfer interface
++ * - @subpage page_iface_wl_shell - create desktop-style surfaces
++ * - @subpage page_iface_wl_shell_surface - desktop-style metadata interface
++ * - @subpage page_iface_wl_surface - an onscreen surface
++ * - @subpage page_iface_wl_seat - group of input devices
++ * - @subpage page_iface_wl_pointer - pointer input device
++ * - @subpage page_iface_wl_keyboard - keyboard input device
++ * - @subpage page_iface_wl_touch - touchscreen input device
++ * - @subpage page_iface_wl_output - compositor output region
++ * - @subpage page_iface_wl_region - region interface
++ * - @subpage page_iface_wl_subcompositor - sub-surface compositing
++ * - @subpage page_iface_wl_subsurface - sub-surface interface to a wl_surface
++ * @section page_copyright_wayland Copyright
++ * <pre>
++ *
++ * Copyright © 2008-2011 Kristian Høgsberg
++ * Copyright © 2010-2011 Intel Corporation
++ * Copyright © 2012-2013 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct wl_buffer;
++struct wl_callback;
++struct wl_compositor;
++struct wl_data_device;
++struct wl_data_device_manager;
++struct wl_data_offer;
++struct wl_data_source;
++struct wl_display;
++struct wl_keyboard;
++struct wl_output;
++struct wl_pointer;
++struct wl_region;
++struct wl_registry;
++struct wl_seat;
++struct wl_shell;
++struct wl_shell_surface;
++struct wl_shm;
++struct wl_shm_pool;
++struct wl_subcompositor;
++struct wl_subsurface;
++struct wl_surface;
++struct wl_touch;
++
++#ifndef WL_DISPLAY_INTERFACE
++#define WL_DISPLAY_INTERFACE
++/**
++ * @page page_iface_wl_display wl_display
++ * @section page_iface_wl_display_desc Description
++ *
++ * The core global object.  This is a special singleton object.  It
++ * is used for internal Wayland protocol features.
++ * @section page_iface_wl_display_api API
++ * See @ref iface_wl_display.
++ */
++/**
++ * @defgroup iface_wl_display The wl_display interface
++ *
++ * The core global object.  This is a special singleton object.  It
++ * is used for internal Wayland protocol features.
++ */
++extern const struct wl_interface wl_display_interface;
++#endif
++#ifndef WL_REGISTRY_INTERFACE
++#define WL_REGISTRY_INTERFACE
++/**
++ * @page page_iface_wl_registry wl_registry
++ * @section page_iface_wl_registry_desc Description
++ *
++ * The singleton global registry object.  The server has a number of
++ * global objects that are available to all clients.  These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry.  Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes.  To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request.  This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ * @section page_iface_wl_registry_api API
++ * See @ref iface_wl_registry.
++ */
++/**
++ * @defgroup iface_wl_registry The wl_registry interface
++ *
++ * The singleton global registry object.  The server has a number of
++ * global objects that are available to all clients.  These objects
++ * typically represent an actual object in the server (for example,
++ * an input device) or they are singleton objects that provide
++ * extension functionality.
++ *
++ * When a client creates a registry object, the registry object
++ * will emit a global event for each global currently in the
++ * registry.  Globals come and go as a result of device or
++ * monitor hotplugs, reconfiguration or other events, and the
++ * registry will send out global and global_remove events to
++ * keep the client up to date with the changes.  To mark the end
++ * of the initial burst of events, the client can use the
++ * wl_display.sync request immediately after calling
++ * wl_display.get_registry.
++ *
++ * A client can bind to a global object by using the bind
++ * request.  This creates a client-side handle that lets the object
++ * emit events to the client and lets the client invoke requests on
++ * the object.
++ */
++extern const struct wl_interface wl_registry_interface;
++#endif
++#ifndef WL_CALLBACK_INTERFACE
++#define WL_CALLBACK_INTERFACE
++/**
++ * @page page_iface_wl_callback wl_callback
++ * @section page_iface_wl_callback_desc Description
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ * @section page_iface_wl_callback_api API
++ * See @ref iface_wl_callback.
++ */
++/**
++ * @defgroup iface_wl_callback The wl_callback interface
++ *
++ * Clients can handle the 'done' event to get notified when
++ * the related request is done.
++ */
++extern const struct wl_interface wl_callback_interface;
++#endif
++#ifndef WL_COMPOSITOR_INTERFACE
++#define WL_COMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_compositor wl_compositor
++ * @section page_iface_wl_compositor_desc Description
++ *
++ * A compositor.  This object is a singleton global.  The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ * @section page_iface_wl_compositor_api API
++ * See @ref iface_wl_compositor.
++ */
++/**
++ * @defgroup iface_wl_compositor The wl_compositor interface
++ *
++ * A compositor.  This object is a singleton global.  The
++ * compositor is in charge of combining the contents of multiple
++ * surfaces into one displayable output.
++ */
++extern const struct wl_interface wl_compositor_interface;
++#endif
++#ifndef WL_SHM_POOL_INTERFACE
++#define WL_SHM_POOL_INTERFACE
++/**
++ * @page page_iface_wl_shm_pool wl_shm_pool
++ * @section page_iface_wl_shm_pool_desc Description
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client.  Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ * @section page_iface_wl_shm_pool_api API
++ * See @ref iface_wl_shm_pool.
++ */
++/**
++ * @defgroup iface_wl_shm_pool The wl_shm_pool interface
++ *
++ * The wl_shm_pool object encapsulates a piece of memory shared
++ * between the compositor and client.  Through the wl_shm_pool
++ * object, the client can allocate shared memory wl_buffer objects.
++ * All objects created through the same pool share the same
++ * underlying mapped memory. Reusing the mapped memory avoids the
++ * setup/teardown overhead and is useful when interactively resizing
++ * a surface or for many small buffers.
++ */
++extern const struct wl_interface wl_shm_pool_interface;
++#endif
++#ifndef WL_SHM_INTERFACE
++#define WL_SHM_INTERFACE
++/**
++ * @page page_iface_wl_shm wl_shm
++ * @section page_iface_wl_shm_desc Description
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ * @section page_iface_wl_shm_api API
++ * See @ref iface_wl_shm.
++ */
++/**
++ * @defgroup iface_wl_shm The wl_shm interface
++ *
++ * A singleton global object that provides support for shared
++ * memory.
++ *
++ * Clients can create wl_shm_pool objects using the create_pool
++ * request.
++ *
++ * At connection setup time, the wl_shm object emits one or more
++ * format events to inform clients about the valid pixel formats
++ * that can be used for buffers.
++ */
++extern const struct wl_interface wl_shm_interface;
++#endif
++#ifndef WL_BUFFER_INTERFACE
++#define WL_BUFFER_INTERFACE
++/**
++ * @page page_iface_wl_buffer wl_buffer
++ * @section page_iface_wl_buffer_desc Description
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ * @section page_iface_wl_buffer_api API
++ * See @ref iface_wl_buffer.
++ */
++/**
++ * @defgroup iface_wl_buffer The wl_buffer interface
++ *
++ * A buffer provides the content for a wl_surface. Buffers are
++ * created through factory interfaces such as wl_drm, wl_shm or
++ * similar. It has a width and a height and can be attached to a
++ * wl_surface, but the mechanism by which a client provides and
++ * updates the contents is defined by the buffer factory interface.
++ */
++extern const struct wl_interface wl_buffer_interface;
++#endif
++#ifndef WL_DATA_OFFER_INTERFACE
++#define WL_DATA_OFFER_INTERFACE
++/**
++ * @page page_iface_wl_data_offer wl_data_offer
++ * @section page_iface_wl_data_offer_desc Description
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client).  It is used by the
++ * copy-and-paste and drag-and-drop mechanisms.  The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ * @section page_iface_wl_data_offer_api API
++ * See @ref iface_wl_data_offer.
++ */
++/**
++ * @defgroup iface_wl_data_offer The wl_data_offer interface
++ *
++ * A wl_data_offer represents a piece of data offered for transfer
++ * by another client (the source client).  It is used by the
++ * copy-and-paste and drag-and-drop mechanisms.  The offer
++ * describes the different mime types that the data can be
++ * converted to and provides the mechanism for transferring the
++ * data directly from the source client.
++ */
++extern const struct wl_interface wl_data_offer_interface;
++#endif
++#ifndef WL_DATA_SOURCE_INTERFACE
++#define WL_DATA_SOURCE_INTERFACE
++/**
++ * @page page_iface_wl_data_source wl_data_source
++ * @section page_iface_wl_data_source_desc Description
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ * @section page_iface_wl_data_source_api API
++ * See @ref iface_wl_data_source.
++ */
++/**
++ * @defgroup iface_wl_data_source The wl_data_source interface
++ *
++ * The wl_data_source object is the source side of a wl_data_offer.
++ * It is created by the source client in a data transfer and
++ * provides a way to describe the offered data and a way to respond
++ * to requests to transfer the data.
++ */
++extern const struct wl_interface wl_data_source_interface;
++#endif
++#ifndef WL_DATA_DEVICE_INTERFACE
++#define WL_DATA_DEVICE_INTERFACE
++/**
++ * @page page_iface_wl_data_device wl_data_device
++ * @section page_iface_wl_data_device_desc Description
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ * @section page_iface_wl_data_device_api API
++ * See @ref iface_wl_data_device.
++ */
++/**
++ * @defgroup iface_wl_data_device The wl_data_device interface
++ *
++ * There is one wl_data_device per seat which can be obtained
++ * from the global wl_data_device_manager singleton.
++ *
++ * A wl_data_device provides access to inter-client data transfer
++ * mechanisms such as copy-and-paste and drag-and-drop.
++ */
++extern const struct wl_interface wl_data_device_interface;
++#endif
++#ifndef WL_DATA_DEVICE_MANAGER_INTERFACE
++#define WL_DATA_DEVICE_MANAGER_INTERFACE
++/**
++ * @page page_iface_wl_data_device_manager wl_data_device_manager
++ * @section page_iface_wl_data_device_manager_desc Description
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop.  These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ * @section page_iface_wl_data_device_manager_api API
++ * See @ref iface_wl_data_device_manager.
++ */
++/**
++ * @defgroup iface_wl_data_device_manager The wl_data_device_manager interface
++ *
++ * The wl_data_device_manager is a singleton global object that
++ * provides access to inter-client data transfer mechanisms such as
++ * copy-and-paste and drag-and-drop.  These mechanisms are tied to
++ * a wl_seat and this interface lets a client get a wl_data_device
++ * corresponding to a wl_seat.
++ *
++ * Depending on the version bound, the objects created from the bound
++ * wl_data_device_manager object will have different requirements for
++ * functioning properly. See wl_data_source.set_actions,
++ * wl_data_offer.accept and wl_data_offer.finish for details.
++ */
++extern const struct wl_interface wl_data_device_manager_interface;
++#endif
++#ifndef WL_SHELL_INTERFACE
++#define WL_SHELL_INTERFACE
++/**
++ * @page page_iface_wl_shell wl_shell
++ * @section page_iface_wl_shell_desc Description
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ * @section page_iface_wl_shell_api API
++ * See @ref iface_wl_shell.
++ */
++/**
++ * @defgroup iface_wl_shell The wl_shell interface
++ *
++ * This interface is implemented by servers that provide
++ * desktop-style user interfaces.
++ *
++ * It allows clients to associate a wl_shell_surface with
++ * a basic surface.
++ */
++extern const struct wl_interface wl_shell_interface;
++#endif
++#ifndef WL_SHELL_SURFACE_INTERFACE
++#define WL_SHELL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_shell_surface wl_shell_surface
++ * @section page_iface_wl_shell_surface_desc Description
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ * @section page_iface_wl_shell_surface_api API
++ * See @ref iface_wl_shell_surface.
++ */
++/**
++ * @defgroup iface_wl_shell_surface The wl_shell_surface interface
++ *
++ * An interface that may be implemented by a wl_surface, for
++ * implementations that provide a desktop-style user interface.
++ *
++ * It provides requests to treat surfaces like toplevel, fullscreen
++ * or popup windows, move, resize or maximize them, associate
++ * metadata like title and class, etc.
++ *
++ * On the server side the object is automatically destroyed when
++ * the related wl_surface is destroyed. On the client side,
++ * wl_shell_surface_destroy() must be called before destroying
++ * the wl_surface object.
++ */
++extern const struct wl_interface wl_shell_surface_interface;
++#endif
++#ifndef WL_SURFACE_INTERFACE
++#define WL_SURFACE_INTERFACE
++/**
++ * @page page_iface_wl_surface wl_surface
++ * @section page_iface_wl_surface_desc Description
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ * @section page_iface_wl_surface_api API
++ * See @ref iface_wl_surface.
++ */
++/**
++ * @defgroup iface_wl_surface The wl_surface interface
++ *
++ * A surface is a rectangular area that is displayed on the screen.
++ * It has a location, size and pixel contents.
++ *
++ * The size of a surface (and relative positions on it) is described
++ * in surface-local coordinates, which may differ from the buffer
++ * coordinates of the pixel content, in case a buffer_transform
++ * or a buffer_scale is used.
++ *
++ * A surface without a "role" is fairly useless: a compositor does
++ * not know where, when or how to present it. The role is the
++ * purpose of a wl_surface. Examples of roles are a cursor for a
++ * pointer (as set by wl_pointer.set_cursor), a drag icon
++ * (wl_data_device.start_drag), a sub-surface
++ * (wl_subcompositor.get_subsurface), and a window as defined by a
++ * shell protocol (e.g. wl_shell.get_shell_surface).
++ *
++ * A surface can have only one role at a time. Initially a
++ * wl_surface does not have a role. Once a wl_surface is given a
++ * role, it is set permanently for the whole lifetime of the
++ * wl_surface object. Giving the current role again is allowed,
++ * unless explicitly forbidden by the relevant interface
++ * specification.
++ *
++ * Surface roles are given by requests in other interfaces such as
++ * wl_pointer.set_cursor. The request should explicitly mention
++ * that this request gives a role to a wl_surface. Often, this
++ * request also creates a new protocol object that represents the
++ * role and adds additional functionality to wl_surface. When a
++ * client wants to destroy a wl_surface, they must destroy this 'role
++ * object' before the wl_surface.
++ *
++ * Destroying the role object does not remove the role from the
++ * wl_surface, but it may stop the wl_surface from "playing the role".
++ * For instance, if a wl_subsurface object is destroyed, the wl_surface
++ * it was created for will be unmapped and forget its position and
++ * z-order. It is allowed to create a wl_subsurface for the same
++ * wl_surface again, but it is not allowed to use the wl_surface as
++ * a cursor (cursor is a different role than sub-surface, and role
++ * switching is not allowed).
++ */
++extern const struct wl_interface wl_surface_interface;
++#endif
++#ifndef WL_SEAT_INTERFACE
++#define WL_SEAT_INTERFACE
++/**
++ * @page page_iface_wl_seat wl_seat
++ * @section page_iface_wl_seat_desc Description
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged.  A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ * @section page_iface_wl_seat_api API
++ * See @ref iface_wl_seat.
++ */
++/**
++ * @defgroup iface_wl_seat The wl_seat interface
++ *
++ * A seat is a group of keyboards, pointer and touch devices. This
++ * object is published as a global during start up, or when such a
++ * device is hot plugged.  A seat typically has a pointer and
++ * maintains a keyboard focus and a pointer focus.
++ */
++extern const struct wl_interface wl_seat_interface;
++#endif
++#ifndef WL_POINTER_INTERFACE
++#define WL_POINTER_INTERFACE
++/**
++ * @page page_iface_wl_pointer wl_pointer
++ * @section page_iface_wl_pointer_desc Description
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ * @section page_iface_wl_pointer_api API
++ * See @ref iface_wl_pointer.
++ */
++/**
++ * @defgroup iface_wl_pointer The wl_pointer interface
++ *
++ * The wl_pointer interface represents one or more input devices,
++ * such as mice, which control the pointer location and pointer_focus
++ * of a seat.
++ *
++ * The wl_pointer interface generates motion, enter and leave
++ * events for the surfaces that the pointer is located over,
++ * and button and axis events for button presses, button releases
++ * and scrolling.
++ */
++extern const struct wl_interface wl_pointer_interface;
++#endif
++#ifndef WL_KEYBOARD_INTERFACE
++#define WL_KEYBOARD_INTERFACE
++/**
++ * @page page_iface_wl_keyboard wl_keyboard
++ * @section page_iface_wl_keyboard_desc Description
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ * @section page_iface_wl_keyboard_api API
++ * See @ref iface_wl_keyboard.
++ */
++/**
++ * @defgroup iface_wl_keyboard The wl_keyboard interface
++ *
++ * The wl_keyboard interface represents one or more keyboards
++ * associated with a seat.
++ */
++extern const struct wl_interface wl_keyboard_interface;
++#endif
++#ifndef WL_TOUCH_INTERFACE
++#define WL_TOUCH_INTERFACE
++/**
++ * @page page_iface_wl_touch wl_touch
++ * @section page_iface_wl_touch_desc Description
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ * @section page_iface_wl_touch_api API
++ * See @ref iface_wl_touch.
++ */
++/**
++ * @defgroup iface_wl_touch The wl_touch interface
++ *
++ * The wl_touch interface represents a touchscreen
++ * associated with a seat.
++ *
++ * Touch interactions can consist of one or more contacts.
++ * For each contact, a series of events is generated, starting
++ * with a down event, followed by zero or more motion events,
++ * and ending with an up event. Events relating to the same
++ * contact point can be identified by the ID of the sequence.
++ */
++extern const struct wl_interface wl_touch_interface;
++#endif
++#ifndef WL_OUTPUT_INTERFACE
++#define WL_OUTPUT_INTERFACE
++/**
++ * @page page_iface_wl_output wl_output
++ * @section page_iface_wl_output_desc Description
++ *
++ * An output describes part of the compositor geometry.  The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible.  This typically corresponds to a monitor that
++ * displays part of the compositor space.  This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ * @section page_iface_wl_output_api API
++ * See @ref iface_wl_output.
++ */
++/**
++ * @defgroup iface_wl_output The wl_output interface
++ *
++ * An output describes part of the compositor geometry.  The
++ * compositor works in the 'compositor coordinate system' and an
++ * output corresponds to a rectangular area in that space that is
++ * actually visible.  This typically corresponds to a monitor that
++ * displays part of the compositor space.  This object is published
++ * as global during start up, or when a monitor is hotplugged.
++ */
++extern const struct wl_interface wl_output_interface;
++#endif
++#ifndef WL_REGION_INTERFACE
++#define WL_REGION_INTERFACE
++/**
++ * @page page_iface_wl_region wl_region
++ * @section page_iface_wl_region_desc Description
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ * @section page_iface_wl_region_api API
++ * See @ref iface_wl_region.
++ */
++/**
++ * @defgroup iface_wl_region The wl_region interface
++ *
++ * A region object describes an area.
++ *
++ * Region objects are used to describe the opaque and input
++ * regions of a surface.
++ */
++extern const struct wl_interface wl_region_interface;
++#endif
++#ifndef WL_SUBCOMPOSITOR_INTERFACE
++#define WL_SUBCOMPOSITOR_INTERFACE
++/**
++ * @page page_iface_wl_subcompositor wl_subcompositor
++ * @section page_iface_wl_subcompositor_desc Description
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ * @section page_iface_wl_subcompositor_api API
++ * See @ref iface_wl_subcompositor.
++ */
++/**
++ * @defgroup iface_wl_subcompositor The wl_subcompositor interface
++ *
++ * The global interface exposing sub-surface compositing capabilities.
++ * A wl_surface, that has sub-surfaces associated, is called the
++ * parent surface. Sub-surfaces can be arbitrarily nested and create
++ * a tree of sub-surfaces.
++ *
++ * The root surface in a tree of sub-surfaces is the main
++ * surface. The main surface cannot be a sub-surface, because
++ * sub-surfaces must always have a parent.
++ *
++ * A main surface with its sub-surfaces forms a (compound) window.
++ * For window management purposes, this set of wl_surface objects is
++ * to be considered as a single window, and it should also behave as
++ * such.
++ *
++ * The aim of sub-surfaces is to offload some of the compositing work
++ * within a window from clients to the compositor. A prime example is
++ * a video player with decorations and video in separate wl_surface
++ * objects. This should allow the compositor to pass YUV video buffer
++ * processing to dedicated overlay hardware when possible.
++ */
++extern const struct wl_interface wl_subcompositor_interface;
++#endif
++#ifndef WL_SUBSURFACE_INTERFACE
++#define WL_SUBSURFACE_INTERFACE
++/**
++ * @page page_iface_wl_subsurface wl_subsurface
++ * @section page_iface_wl_subsurface_desc Description
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ * @section page_iface_wl_subsurface_api API
++ * See @ref iface_wl_subsurface.
++ */
++/**
++ * @defgroup iface_wl_subsurface The wl_subsurface interface
++ *
++ * An additional interface to a wl_surface object, which has been
++ * made a sub-surface. A sub-surface has one parent surface. A
++ * sub-surface's size and position are not limited to that of the parent.
++ * Particularly, a sub-surface is not automatically clipped to its
++ * parent's area.
++ *
++ * A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++ * and the parent surface is mapped. The order of which one happens
++ * first is irrelevant. A sub-surface is hidden if the parent becomes
++ * hidden, or if a NULL wl_buffer is applied. These rules apply
++ * recursively through the tree of surfaces.
++ *
++ * The behaviour of a wl_surface.commit request on a sub-surface
++ * depends on the sub-surface's mode. The possible modes are
++ * synchronized and desynchronized, see methods
++ * wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++ * mode caches the wl_surface state to be applied when the parent's
++ * state gets applied, and desynchronized mode applies the pending
++ * wl_surface state directly. A sub-surface is initially in the
++ * synchronized mode.
++ *
++ * Sub-surfaces have also other kind of state, which is managed by
++ * wl_subsurface requests, as opposed to wl_surface requests. This
++ * state includes the sub-surface position relative to the parent
++ * surface (wl_subsurface.set_position), and the stacking order of
++ * the parent and its sub-surfaces (wl_subsurface.place_above and
++ * .place_below). This state is applied when the parent surface's
++ * wl_surface state is applied, regardless of the sub-surface's mode.
++ * As the exception, set_sync and set_desync are effective immediately.
++ *
++ * The main surface can be thought to be always in desynchronized mode,
++ * since it does not have a parent in the sub-surfaces sense.
++ *
++ * Even if a sub-surface is in desynchronized mode, it will behave as
++ * in synchronized mode, if its parent surface behaves as in
++ * synchronized mode. This rule is applied recursively throughout the
++ * tree of surfaces. This means, that one can set a sub-surface into
++ * synchronized mode, and then assume that all its child and grand-child
++ * sub-surfaces are synchronized, too, without explicitly setting them.
++ *
++ * If the wl_surface associated with the wl_subsurface is destroyed, the
++ * wl_subsurface object becomes inert. Note, that destroying either object
++ * takes effect immediately. If you need to synchronize the removal
++ * of a sub-surface to the parent surface update, unmap the sub-surface
++ * first by attaching a NULL wl_buffer, update parent, and then destroy
++ * the sub-surface.
++ *
++ * If the parent wl_surface object is destroyed, the sub-surface is
++ * unmapped.
++ */
++extern const struct wl_interface wl_subsurface_interface;
++#endif
++
++#ifndef WL_DISPLAY_ERROR_ENUM
++#define WL_DISPLAY_ERROR_ENUM
++/**
++ * @ingroup iface_wl_display
++ * global error values
++ *
++ * These errors are global and can be emitted in response to any
++ * server request.
++ */
++enum wl_display_error {
++      /**
++       * server couldn't find object
++       */
++      WL_DISPLAY_ERROR_INVALID_OBJECT = 0,
++      /**
++       * method doesn't exist on the specified interface
++       */
++      WL_DISPLAY_ERROR_INVALID_METHOD = 1,
++      /**
++       * server is out of memory
++       */
++      WL_DISPLAY_ERROR_NO_MEMORY = 2,
++};
++#endif /* WL_DISPLAY_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_display
++ * @struct wl_display_interface
++ */
++struct wl_display_interface {
++      /**
++       * asynchronous roundtrip
++       *
++       * The sync request asks the server to emit the 'done' event on
++       * the returned wl_callback object. Since requests are handled
++       * in-order and events are delivered in-order, this can be used as
++       * a barrier to ensure all previous requests and the resulting
++       * events have been handled.
++       *
++       * The object returned by this request will be destroyed by the
++       * compositor after the callback is fired and as such the client
++       * must not attempt to use it after that point.
++       *
++       * The callback_data passed in the callback is the event serial.
++       * @param callback callback object for the sync request
++       */
++      void (*sync)(struct wl_client *client,
++                   struct wl_resource *resource,
++                   uint32_t callback);
++      /**
++       * get global registry object
++       *
++       * This request creates a registry object that allows the client
++       * to list and bind the global objects available from the
++       * compositor.
++       * @param registry global registry object
++       */
++      void (*get_registry)(struct wl_client *client,
++                           struct wl_resource *resource,
++                           uint32_t registry);
++};
++
++#define WL_DISPLAY_ERROR 0
++#define WL_DISPLAY_DELETE_ID 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_ERROR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_DELETE_ID_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_display
++ */
++#define WL_DISPLAY_GET_REGISTRY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ * @struct wl_registry_interface
++ */
++struct wl_registry_interface {
++      /**
++       * bind an object to the display
++       *
++       * Binds a new, client-created object to the server using the
++       * specified name as the identifier.
++       * @param name unique numeric name of the object
++       * @param interface name of the objects interface
++       * @param version version of the objects interface
++       * @param id bounded object
++       */
++      void (*bind)(struct wl_client *client,
++                   struct wl_resource *resource,
++                   uint32_t name,
++                   const char *interface, uint32_t version, uint32_t id);
++};
++
++#define WL_REGISTRY_GLOBAL 0
++#define WL_REGISTRY_GLOBAL_REMOVE 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_GLOBAL_REMOVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ */
++#define WL_REGISTRY_BIND_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_registry
++ * Sends an global event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name numeric name of the global object
++ * @param interface interface implemented by the object
++ * @param version interface version
++ */
++static inline void
++wl_registry_send_global(struct wl_resource *resource_, uint32_t name, const char *interface, uint32_t version)
++{
++      wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL, name, interface, version);
++}
++
++/**
++ * @ingroup iface_wl_registry
++ * Sends an global_remove event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name numeric name of the global object
++ */
++static inline void
++wl_registry_send_global_remove(struct wl_resource *resource_, uint32_t name)
++{
++      wl_resource_post_event(resource_, WL_REGISTRY_GLOBAL_REMOVE, name);
++}
++
++#define WL_CALLBACK_DONE 0
++
++/**
++ * @ingroup iface_wl_callback
++ */
++#define WL_CALLBACK_DONE_SINCE_VERSION 1
++
++
++/**
++ * @ingroup iface_wl_callback
++ * Sends an done event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param callback_data request-specific data for the callback
++ */
++static inline void
++wl_callback_send_done(struct wl_resource *resource_, uint32_t callback_data)
++{
++      wl_resource_post_event(resource_, WL_CALLBACK_DONE, callback_data);
++}
++
++/**
++ * @ingroup iface_wl_compositor
++ * @struct wl_compositor_interface
++ */
++struct wl_compositor_interface {
++      /**
++       * create new surface
++       *
++       * Ask the compositor to create a new surface.
++       * @param id the new surface
++       */
++      void (*create_surface)(struct wl_client *client,
++                             struct wl_resource *resource,
++                             uint32_t id);
++      /**
++       * create new region
++       *
++       * Ask the compositor to create a new region.
++       * @param id the new region
++       */
++      void (*create_region)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            uint32_t id);
++};
++
++
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_SURFACE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_compositor
++ */
++#define WL_COMPOSITOR_CREATE_REGION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm_pool
++ * @struct wl_shm_pool_interface
++ */
++struct wl_shm_pool_interface {
++      /**
++       * create a buffer from the pool
++       *
++       * Create a wl_buffer object from the pool.
++       *
++       * The buffer is created offset bytes into the pool and has width
++       * and height as specified. The stride argument specifies the
++       * number of bytes from the beginning of one row to the beginning
++       * of the next. The format is the pixel format of the buffer and
++       * must be one of those advertised through the wl_shm.format event.
++       *
++       * A buffer will keep a reference to the pool it was created from
++       * so it is valid to destroy the pool immediately after creating a
++       * buffer from it.
++       * @param id buffer to create
++       * @param offset buffer byte offset within the pool
++       * @param width buffer width, in pixels
++       * @param height buffer height, in pixels
++       * @param stride number of bytes from the beginning of one row to the beginning of the next row
++       * @param format buffer pixel format
++       */
++      void (*create_buffer)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            uint32_t id,
++                            int32_t offset,
++                            int32_t width,
++                            int32_t height,
++                            int32_t stride,
++                            uint32_t format);
++      /**
++       * destroy the pool
++       *
++       * Destroy the shared memory pool.
++       *
++       * The mmapped memory will be released when all buffers that have
++       * been created from this pool are gone.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * change the size of the pool mapping
++       *
++       * This request will cause the server to remap the backing memory
++       * for the pool from the file descriptor passed when the pool was
++       * created, but using the new size. This request can only be used
++       * to make the pool bigger.
++       * @param size new size of the pool, in bytes
++       */
++      void (*resize)(struct wl_client *client,
++                     struct wl_resource *resource,
++                     int32_t size);
++};
++
++
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_CREATE_BUFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shm_pool
++ */
++#define WL_SHM_POOL_RESIZE_SINCE_VERSION 1
++
++#ifndef WL_SHM_ERROR_ENUM
++#define WL_SHM_ERROR_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * wl_shm error values
++ *
++ * These errors can be emitted in response to wl_shm requests.
++ */
++enum wl_shm_error {
++      /**
++       * buffer format is not known
++       */
++      WL_SHM_ERROR_INVALID_FORMAT = 0,
++      /**
++       * invalid size or stride during pool or buffer creation
++       */
++      WL_SHM_ERROR_INVALID_STRIDE = 1,
++      /**
++       * mmapping the file descriptor failed
++       */
++      WL_SHM_ERROR_INVALID_FD = 2,
++};
++#endif /* WL_SHM_ERROR_ENUM */
++
++#ifndef WL_SHM_FORMAT_ENUM
++#define WL_SHM_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_shm
++ * pixel formats
++ *
++ * This describes the memory layout of an individual pixel.
++ *
++ * All renderers should support argb8888 and xrgb8888 but any other
++ * formats are optional and may not be supported by the particular
++ * renderer in use.
++ *
++ * The drm format codes match the macros defined in drm_fourcc.h.
++ * The formats actually supported by the compositor will be
++ * reported by the format event.
++ */
++enum wl_shm_format {
++      /**
++       * 32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_ARGB8888 = 0,
++      /**
++       * 32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_XRGB8888 = 1,
++      /**
++       * 8-bit color index format, [7:0] C
++       */
++      WL_SHM_FORMAT_C8 = 0x20203843,
++      /**
++       * 8-bit RGB format, [7:0] R:G:B 3:3:2
++       */
++      WL_SHM_FORMAT_RGB332 = 0x38424752,
++      /**
++       * 8-bit BGR format, [7:0] B:G:R 2:3:3
++       */
++      WL_SHM_FORMAT_BGR233 = 0x38524742,
++      /**
++       * 16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_XRGB4444 = 0x32315258,
++      /**
++       * 16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_XBGR4444 = 0x32314258,
++      /**
++       * 16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_RGBX4444 = 0x32315852,
++      /**
++       * 16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_BGRX4444 = 0x32315842,
++      /**
++       * 16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_ARGB4444 = 0x32315241,
++      /**
++       * 16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_ABGR4444 = 0x32314241,
++      /**
++       * 16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_RGBA4444 = 0x32314152,
++      /**
++       * 16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian
++       */
++      WL_SHM_FORMAT_BGRA4444 = 0x32314142,
++      /**
++       * 16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_XRGB1555 = 0x35315258,
++      /**
++       * 16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_XBGR1555 = 0x35314258,
++      /**
++       * 16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_RGBX5551 = 0x35315852,
++      /**
++       * 16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_BGRX5551 = 0x35315842,
++      /**
++       * 16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_ARGB1555 = 0x35315241,
++      /**
++       * 16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian
++       */
++      WL_SHM_FORMAT_ABGR1555 = 0x35314241,
++      /**
++       * 16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_RGBA5551 = 0x35314152,
++      /**
++       * 16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian
++       */
++      WL_SHM_FORMAT_BGRA5551 = 0x35314142,
++      /**
++       * 16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian
++       */
++      WL_SHM_FORMAT_RGB565 = 0x36314752,
++      /**
++       * 16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian
++       */
++      WL_SHM_FORMAT_BGR565 = 0x36314742,
++      /**
++       * 24-bit RGB format, [23:0] R:G:B little endian
++       */
++      WL_SHM_FORMAT_RGB888 = 0x34324752,
++      /**
++       * 24-bit BGR format, [23:0] B:G:R little endian
++       */
++      WL_SHM_FORMAT_BGR888 = 0x34324742,
++      /**
++       * 32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_XBGR8888 = 0x34324258,
++      /**
++       * 32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_RGBX8888 = 0x34325852,
++      /**
++       * 32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_BGRX8888 = 0x34325842,
++      /**
++       * 32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_ABGR8888 = 0x34324241,
++      /**
++       * 32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_RGBA8888 = 0x34324152,
++      /**
++       * 32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_BGRA8888 = 0x34324142,
++      /**
++       * 32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_XRGB2101010 = 0x30335258,
++      /**
++       * 32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_XBGR2101010 = 0x30334258,
++      /**
++       * 32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_RGBX1010102 = 0x30335852,
++      /**
++       * 32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_BGRX1010102 = 0x30335842,
++      /**
++       * 32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_ARGB2101010 = 0x30335241,
++      /**
++       * 32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian
++       */
++      WL_SHM_FORMAT_ABGR2101010 = 0x30334241,
++      /**
++       * 32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_RGBA1010102 = 0x30334152,
++      /**
++       * 32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian
++       */
++      WL_SHM_FORMAT_BGRA1010102 = 0x30334142,
++      /**
++       * packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_YUYV = 0x56595559,
++      /**
++       * packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_YVYU = 0x55595659,
++      /**
++       * packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_UYVY = 0x59565955,
++      /**
++       * packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_VYUY = 0x59555956,
++      /**
++       * packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian
++       */
++      WL_SHM_FORMAT_AYUV = 0x56555941,
++      /**
++       * 2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane
++       */
++      WL_SHM_FORMAT_NV12 = 0x3231564e,
++      /**
++       * 2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane
++       */
++      WL_SHM_FORMAT_NV21 = 0x3132564e,
++      /**
++       * 2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane
++       */
++      WL_SHM_FORMAT_NV16 = 0x3631564e,
++      /**
++       * 2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane
++       */
++      WL_SHM_FORMAT_NV61 = 0x3136564e,
++      /**
++       * 3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV410 = 0x39565559,
++      /**
++       * 3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU410 = 0x39555659,
++      /**
++       * 3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV411 = 0x31315559,
++      /**
++       * 3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU411 = 0x31315659,
++      /**
++       * 3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV420 = 0x32315559,
++      /**
++       * 3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU420 = 0x32315659,
++      /**
++       * 3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV422 = 0x36315559,
++      /**
++       * 3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU422 = 0x36315659,
++      /**
++       * 3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes
++       */
++      WL_SHM_FORMAT_YUV444 = 0x34325559,
++      /**
++       * 3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes
++       */
++      WL_SHM_FORMAT_YVU444 = 0x34325659,
++};
++#endif /* WL_SHM_FORMAT_ENUM */
++
++/**
++ * @ingroup iface_wl_shm
++ * @struct wl_shm_interface
++ */
++struct wl_shm_interface {
++      /**
++       * create a shm pool
++       *
++       * Create a new wl_shm_pool object.
++       *
++       * The pool can be used to create shared memory based buffer
++       * objects. The server will mmap size bytes of the passed file
++       * descriptor, to use as backing memory for the pool.
++       * @param id pool to create
++       * @param fd file descriptor for the pool
++       * @param size pool size, in bytes
++       */
++      void (*create_pool)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          uint32_t id,
++                          int32_t fd,
++                          int32_t size);
++};
++
++#define WL_SHM_FORMAT 0
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_FORMAT_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ */
++#define WL_SHM_CREATE_POOL_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shm
++ * Sends an format event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param format buffer pixel format
++ */
++static inline void
++wl_shm_send_format(struct wl_resource *resource_, uint32_t format)
++{
++      wl_resource_post_event(resource_, WL_SHM_FORMAT, format);
++}
++
++/**
++ * @ingroup iface_wl_buffer
++ * @struct wl_buffer_interface
++ */
++struct wl_buffer_interface {
++      /**
++       * destroy a buffer
++       *
++       * Destroy a buffer. If and how you need to release the backing
++       * storage is defined by the buffer factory interface.
++       *
++       * For possible side-effects to a surface, see wl_surface.attach.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_BUFFER_RELEASE 0
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_RELEASE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ */
++#define WL_BUFFER_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_buffer
++ * Sends an release event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_buffer_send_release(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_BUFFER_RELEASE);
++}
++
++#ifndef WL_DATA_OFFER_ERROR_ENUM
++#define WL_DATA_OFFER_ERROR_ENUM
++enum wl_data_offer_error {
++      /**
++       * finish request was called untimely
++       */
++      WL_DATA_OFFER_ERROR_INVALID_FINISH = 0,
++      /**
++       * action mask contains invalid values
++       */
++      WL_DATA_OFFER_ERROR_INVALID_ACTION_MASK = 1,
++      /**
++       * action argument has an invalid value
++       */
++      WL_DATA_OFFER_ERROR_INVALID_ACTION = 2,
++      /**
++       * offer doesn't accept this request
++       */
++      WL_DATA_OFFER_ERROR_INVALID_OFFER = 3,
++};
++#endif /* WL_DATA_OFFER_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_offer
++ * @struct wl_data_offer_interface
++ */
++struct wl_data_offer_interface {
++      /**
++       * accept one of the offered mime types
++       *
++       * Indicate that the client can accept the given mime type, or
++       * NULL for not accepted.
++       *
++       * For objects of version 2 or older, this request is used by the
++       * client to give feedback whether the client can receive the given
++       * mime type, or NULL if none is accepted; the feedback does not
++       * determine whether the drag-and-drop operation succeeds or not.
++       *
++       * For objects of version 3 or newer, this request determines the
++       * final result of the drag-and-drop operation. If the end result
++       * is that no mime types were accepted, the drag-and-drop operation
++       * will be cancelled and the corresponding drag source will receive
++       * wl_data_source.cancelled. Clients may still use this event in
++       * conjunction with wl_data_source.action for feedback.
++       * @param serial serial number of the accept request
++       * @param mime_type mime type accepted by the client
++       */
++      void (*accept)(struct wl_client *client,
++                     struct wl_resource *resource,
++                     uint32_t serial,
++                     const char *mime_type);
++      /**
++       * request that the data is transferred
++       *
++       * To transfer the offered data, the client issues this request
++       * and indicates the mime type it wants to receive. The transfer
++       * happens through the passed file descriptor (typically created
++       * with the pipe system call). The source client writes the data in
++       * the mime type representation requested and then closes the file
++       * descriptor.
++       *
++       * The receiving client reads from the read end of the pipe until
++       * EOF and then closes its end, at which point the transfer is
++       * complete.
++       *
++       * This request may happen multiple times for different mime types,
++       * both before and after wl_data_device.drop. Drag-and-drop
++       * destination clients may preemptively fetch data or examine it
++       * more closely to determine acceptance.
++       * @param mime_type mime type desired by receiver
++       * @param fd file descriptor for data transfer
++       */
++      void (*receive)(struct wl_client *client,
++                      struct wl_resource *resource,
++                      const char *mime_type,
++                      int32_t fd);
++      /**
++       * destroy data offer
++       *
++       * Destroy the data offer.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * the offer will no longer be used
++       *
++       * Notifies the compositor that the drag destination successfully
++       * finished the drag-and-drop operation.
++       *
++       * Upon receiving this request, the compositor will emit
++       * wl_data_source.dnd_finished on the drag source client.
++       *
++       * It is a client error to perform other requests than
++       * wl_data_offer.destroy after this one. It is also an error to
++       * perform this request after a NULL mime type has been set in
++       * wl_data_offer.accept or no action was received through
++       * wl_data_offer.action.
++       * @since 3
++       */
++      void (*finish)(struct wl_client *client,
++                     struct wl_resource *resource);
++      /**
++       * set the available/preferred drag-and-drop actions
++       *
++       * Sets the actions that the destination side client supports for
++       * this operation. This request may trigger the emission of
++       * wl_data_source.action and wl_data_offer.action events if the
++       * compositor needs to change the selected action.
++       *
++       * This request can be called multiple times throughout the
++       * drag-and-drop operation, typically in response to
++       * wl_data_device.enter or wl_data_device.motion events.
++       *
++       * This request determines the final result of the drag-and-drop
++       * operation. If the end result is that no action is accepted, the
++       * drag source will receive wl_drag_source.cancelled.
++       *
++       * The dnd_actions argument must contain only values expressed in
++       * the wl_data_device_manager.dnd_actions enum, and the
++       * preferred_action argument must only contain one of those values
++       * set, otherwise it will result in a protocol error.
++       *
++       * While managing an "ask" action, the destination drag-and-drop
++       * client may perform further wl_data_offer.receive requests, and
++       * is expected to perform one last wl_data_offer.set_actions
++       * request with a preferred action other than "ask" (and optionally
++       * wl_data_offer.accept) before requesting wl_data_offer.finish, in
++       * order to convey the action selected by the user. If the
++       * preferred action is not in the wl_data_offer.source_actions
++       * mask, an error will be raised.
++       *
++       * If the "ask" action is dismissed (e.g. user cancellation), the
++       * client is expected to perform wl_data_offer.destroy right away.
++       *
++       * This request can only be made on drag-and-drop offers, a
++       * protocol error will be raised otherwise.
++       * @param dnd_actions actions supported by the destination client
++       * @param preferred_action action preferred by the destination client
++       * @since 3
++       */
++      void (*set_actions)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          uint32_t dnd_actions,
++                          uint32_t preferred_action);
++};
++
++#define WL_DATA_OFFER_OFFER 0
++#define WL_DATA_OFFER_SOURCE_ACTIONS 1
++#define WL_DATA_OFFER_ACTION 2
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SOURCE_ACTIONS_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_ACCEPT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_RECEIVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_FINISH_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_offer
++ */
++#define WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an offer event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type offered mime type
++ */
++static inline void
++wl_data_offer_send_offer(struct wl_resource *resource_, const char *mime_type)
++{
++      wl_resource_post_event(resource_, WL_DATA_OFFER_OFFER, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an source_actions event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param source_actions actions offered by the data source
++ */
++static inline void
++wl_data_offer_send_source_actions(struct wl_resource *resource_, uint32_t source_actions)
++{
++      wl_resource_post_event(resource_, WL_DATA_OFFER_SOURCE_ACTIONS, source_actions);
++}
++
++/**
++ * @ingroup iface_wl_data_offer
++ * Sends an action event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param dnd_action action selected by the compositor
++ */
++static inline void
++wl_data_offer_send_action(struct wl_resource *resource_, uint32_t dnd_action)
++{
++      wl_resource_post_event(resource_, WL_DATA_OFFER_ACTION, dnd_action);
++}
++
++#ifndef WL_DATA_SOURCE_ERROR_ENUM
++#define WL_DATA_SOURCE_ERROR_ENUM
++enum wl_data_source_error {
++      /**
++       * action mask contains invalid values
++       */
++      WL_DATA_SOURCE_ERROR_INVALID_ACTION_MASK = 0,
++      /**
++       * source doesn't accept this request
++       */
++      WL_DATA_SOURCE_ERROR_INVALID_SOURCE = 1,
++};
++#endif /* WL_DATA_SOURCE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_source
++ * @struct wl_data_source_interface
++ */
++struct wl_data_source_interface {
++      /**
++       * add an offered mime type
++       *
++       * This request adds a mime type to the set of mime types
++       * advertised to targets. Can be called several times to offer
++       * multiple types.
++       * @param mime_type mime type offered by the data source
++       */
++      void (*offer)(struct wl_client *client,
++                    struct wl_resource *resource,
++                    const char *mime_type);
++      /**
++       * destroy the data source
++       *
++       * Destroy the data source.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * set the available drag-and-drop actions
++       *
++       * Sets the actions that the source side client supports for this
++       * operation. This request may trigger wl_data_source.action and
++       * wl_data_offer.action events if the compositor needs to change
++       * the selected action.
++       *
++       * The dnd_actions argument must contain only values expressed in
++       * the wl_data_device_manager.dnd_actions enum, otherwise it will
++       * result in a protocol error.
++       *
++       * This request must be made once only, and can only be made on
++       * sources used in drag-and-drop, so it must be performed before
++       * wl_data_device.start_drag. Attempting to use the source other
++       * than for drag-and-drop will raise a protocol error.
++       * @param dnd_actions actions supported by the data source
++       * @since 3
++       */
++      void (*set_actions)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          uint32_t dnd_actions);
++};
++
++#define WL_DATA_SOURCE_TARGET 0
++#define WL_DATA_SOURCE_SEND 1
++#define WL_DATA_SOURCE_CANCELLED 2
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED 3
++#define WL_DATA_SOURCE_DND_FINISHED 4
++#define WL_DATA_SOURCE_ACTION 5
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_TARGET_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SEND_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_CANCELLED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_DROP_PERFORMED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DND_FINISHED_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_ACTION_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_source
++ */
++#define WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an target event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type mime type accepted by the target
++ */
++static inline void
++wl_data_source_send_target(struct wl_resource *resource_, const char *mime_type)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_TARGET, mime_type);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an send event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param mime_type mime type for the data
++ * @param fd file descriptor for the data
++ */
++static inline void
++wl_data_source_send_send(struct wl_resource *resource_, const char *mime_type, int32_t fd)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_SEND, mime_type, fd);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an cancelled event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_cancelled(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_CANCELLED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an dnd_drop_performed event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_dnd_drop_performed(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_DROP_PERFORMED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an dnd_finished event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_source_send_dnd_finished(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_DND_FINISHED);
++}
++
++/**
++ * @ingroup iface_wl_data_source
++ * Sends an action event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param dnd_action action selected by the compositor
++ */
++static inline void
++wl_data_source_send_action(struct wl_resource *resource_, uint32_t dnd_action)
++{
++      wl_resource_post_event(resource_, WL_DATA_SOURCE_ACTION, dnd_action);
++}
++
++#ifndef WL_DATA_DEVICE_ERROR_ENUM
++#define WL_DATA_DEVICE_ERROR_ENUM
++enum wl_data_device_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_DATA_DEVICE_ERROR_ROLE = 0,
++};
++#endif /* WL_DATA_DEVICE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device
++ * @struct wl_data_device_interface
++ */
++struct wl_data_device_interface {
++      /**
++       * start drag-and-drop operation
++       *
++       * This request asks the compositor to start a drag-and-drop
++       * operation on behalf of the client.
++       *
++       * The source argument is the data source that provides the data
++       * for the eventual data transfer. If source is NULL, enter, leave
++       * and motion events are sent only to the client that initiated the
++       * drag and the client is expected to handle the data passing
++       * internally.
++       *
++       * The origin surface is the surface where the drag originates and
++       * the client must have an active implicit grab that matches the
++       * serial.
++       *
++       * The icon surface is an optional (can be NULL) surface that
++       * provides an icon to be moved around with the cursor. Initially,
++       * the top-left corner of the icon surface is placed at the cursor
++       * hotspot, but subsequent wl_surface.attach request can move the
++       * relative position. Attach requests must be confirmed with
++       * wl_surface.commit as usual. The icon surface is given the role
++       * of a drag-and-drop icon. If the icon surface already has another
++       * role, it raises a protocol error.
++       *
++       * The current and pending input regions of the icon wl_surface are
++       * cleared, and wl_surface.set_input_region is ignored until the
++       * wl_surface is no longer used as the icon surface. When the use
++       * as an icon ends, the current and pending input regions become
++       * undefined, and the wl_surface is unmapped.
++       * @param source data source for the eventual transfer
++       * @param origin surface where the drag originates
++       * @param icon drag-and-drop icon surface
++       * @param serial serial number of the implicit grab on the origin
++       */
++      void (*start_drag)(struct wl_client *client,
++                         struct wl_resource *resource,
++                         struct wl_resource *source,
++                         struct wl_resource *origin,
++                         struct wl_resource *icon,
++                         uint32_t serial);
++      /**
++       * copy data to the selection
++       *
++       * This request asks the compositor to set the selection to the
++       * data from the source on behalf of the client.
++       *
++       * To unset the selection, set the source to NULL.
++       * @param source data source for the selection
++       * @param serial serial number of the event that triggered this request
++       */
++      void (*set_selection)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            struct wl_resource *source,
++                            uint32_t serial);
++      /**
++       * destroy data device
++       *
++       * This request destroys the data device.
++       * @since 2
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_DATA_DEVICE_DATA_OFFER 0
++#define WL_DATA_DEVICE_ENTER 1
++#define WL_DATA_DEVICE_LEAVE 2
++#define WL_DATA_DEVICE_MOTION 3
++#define WL_DATA_DEVICE_DROP 4
++#define WL_DATA_DEVICE_SELECTION 5
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DATA_OFFER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_DROP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SELECTION_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_START_DRAG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_SET_SELECTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device
++ */
++#define WL_DATA_DEVICE_RELEASE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an data_offer event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the new data_offer object
++ */
++static inline void
++wl_data_device_send_data_offer(struct wl_resource *resource_, struct wl_resource *id)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_DATA_OFFER, id);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface client surface entered
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ * @param id source data_offer object
++ */
++static inline void
++wl_data_device_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t x, wl_fixed_t y, struct wl_resource *id)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_ENTER, serial, surface, x, y, id);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_device_send_leave(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_LEAVE);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_data_device_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t x, wl_fixed_t y)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_MOTION, time, x, y);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an drop event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_data_device_send_drop(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_DROP);
++}
++
++/**
++ * @ingroup iface_wl_data_device
++ * Sends an selection event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id selection data_offer object
++ */
++static inline void
++wl_data_device_send_selection(struct wl_resource *resource_, struct wl_resource *id)
++{
++      wl_resource_post_event(resource_, WL_DATA_DEVICE_SELECTION, id);
++}
++
++#ifndef WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++#define WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM
++/**
++ * @ingroup iface_wl_data_device_manager
++ * drag and drop actions
++ *
++ * This is a bitmask of the available/preferred actions in a
++ * drag-and-drop operation.
++ *
++ * In the compositor, the selected action is a result of matching the
++ * actions offered by the source and destination sides.  "action" events
++ * with a "none" action will be sent to both source and destination if
++ * there is no match. All further checks will effectively happen on
++ * (source actions ∩ destination actions).
++ *
++ * In addition, compositors may also pick different actions in
++ * reaction to key modifiers being pressed. One common design that
++ * is used in major toolkits (and the behavior recommended for
++ * compositors) is:
++ *
++ * - If no modifiers are pressed, the first match (in bit order)
++ * will be used.
++ * - Pressing Shift selects "move", if enabled in the mask.
++ * - Pressing Control selects "copy", if enabled in the mask.
++ *
++ * Behavior beyond that is considered implementation-dependent.
++ * Compositors may for example bind other modifiers (like Alt/Meta)
++ * or drags initiated with other buttons than BTN_LEFT to specific
++ * actions (e.g. "ask").
++ */
++enum wl_data_device_manager_dnd_action {
++      /**
++       * no action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE = 0,
++      /**
++       * copy action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY = 1,
++      /**
++       * move action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE = 2,
++      /**
++       * ask action
++       */
++      WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK = 4,
++};
++#endif /* WL_DATA_DEVICE_MANAGER_DND_ACTION_ENUM */
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ * @struct wl_data_device_manager_interface
++ */
++struct wl_data_device_manager_interface {
++      /**
++       * create a new data source
++       *
++       * Create a new data source.
++       * @param id data source to create
++       */
++      void (*create_data_source)(struct wl_client *client,
++                                 struct wl_resource *resource,
++                                 uint32_t id);
++      /**
++       * create a new data device
++       *
++       * Create a new data device for a given seat.
++       * @param id data device to create
++       * @param seat seat associated with the data device
++       */
++      void (*get_data_device)(struct wl_client *client,
++                              struct wl_resource *resource,
++                              uint32_t id,
++                              struct wl_resource *seat);
++};
++
++
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_CREATE_DATA_SOURCE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_data_device_manager
++ */
++#define WL_DATA_DEVICE_MANAGER_GET_DATA_DEVICE_SINCE_VERSION 1
++
++#ifndef WL_SHELL_ERROR_ENUM
++#define WL_SHELL_ERROR_ENUM
++enum wl_shell_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_SHELL_ERROR_ROLE = 0,
++};
++#endif /* WL_SHELL_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_shell
++ * @struct wl_shell_interface
++ */
++struct wl_shell_interface {
++      /**
++       * create a shell surface from a surface
++       *
++       * Create a shell surface for an existing surface. This gives the
++       * wl_surface the role of a shell surface. If the wl_surface
++       * already has another role, it raises a protocol error.
++       *
++       * Only one shell surface can be associated with a given surface.
++       * @param id shell surface to create
++       * @param surface surface to be given the shell surface role
++       */
++      void (*get_shell_surface)(struct wl_client *client,
++                                struct wl_resource *resource,
++                                uint32_t id,
++                                struct wl_resource *surface);
++};
++
++
++/**
++ * @ingroup iface_wl_shell
++ */
++#define WL_SHELL_GET_SHELL_SURFACE_SINCE_VERSION 1
++
++#ifndef WL_SHELL_SURFACE_RESIZE_ENUM
++#define WL_SHELL_SURFACE_RESIZE_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * edge values for resizing
++ *
++ * These values are used to indicate which edge of a surface
++ * is being dragged in a resize operation. The server may
++ * use this information to adapt its behavior, e.g. choose
++ * an appropriate cursor image.
++ */
++enum wl_shell_surface_resize {
++      /**
++       * no edge
++       */
++      WL_SHELL_SURFACE_RESIZE_NONE = 0,
++      /**
++       * top edge
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP = 1,
++      /**
++       * bottom edge
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM = 2,
++      /**
++       * left edge
++       */
++      WL_SHELL_SURFACE_RESIZE_LEFT = 4,
++      /**
++       * top and left edges
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP_LEFT = 5,
++      /**
++       * bottom and left edges
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT = 6,
++      /**
++       * right edge
++       */
++      WL_SHELL_SURFACE_RESIZE_RIGHT = 8,
++      /**
++       * top and right edges
++       */
++      WL_SHELL_SURFACE_RESIZE_TOP_RIGHT = 9,
++      /**
++       * bottom and right edges
++       */
++      WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT = 10,
++};
++#endif /* WL_SHELL_SURFACE_RESIZE_ENUM */
++
++#ifndef WL_SHELL_SURFACE_TRANSIENT_ENUM
++#define WL_SHELL_SURFACE_TRANSIENT_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * details of transient behaviour
++ *
++ * These flags specify details of the expected behaviour
++ * of transient surfaces. Used in the set_transient request.
++ */
++enum wl_shell_surface_transient {
++      /**
++       * do not set keyboard focus
++       */
++      WL_SHELL_SURFACE_TRANSIENT_INACTIVE = 0x1,
++};
++#endif /* WL_SHELL_SURFACE_TRANSIENT_ENUM */
++
++#ifndef WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++#define WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM
++/**
++ * @ingroup iface_wl_shell_surface
++ * different method to set the surface fullscreen
++ *
++ * Hints to indicate to the compositor how to deal with a conflict
++ * between the dimensions of the surface and the dimensions of the
++ * output. The compositor is free to ignore this parameter.
++ */
++enum wl_shell_surface_fullscreen_method {
++      /**
++       * no preference, apply default policy
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT = 0,
++      /**
++       * scale, preserve the surface's aspect ratio and center on output
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE = 1,
++      /**
++       * switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER = 2,
++      /**
++       * no upscaling, center on output and add black borders to compensate size mismatch
++       */
++      WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL = 3,
++};
++#endif /* WL_SHELL_SURFACE_FULLSCREEN_METHOD_ENUM */
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * @struct wl_shell_surface_interface
++ */
++struct wl_shell_surface_interface {
++      /**
++       * respond to a ping event
++       *
++       * A client must respond to a ping event with a pong request or
++       * the client may be deemed unresponsive.
++       * @param serial serial number of the ping event
++       */
++      void (*pong)(struct wl_client *client,
++                   struct wl_resource *resource,
++                   uint32_t serial);
++      /**
++       * start an interactive move
++       *
++       * Start a pointer-driven move of the surface.
++       *
++       * This request must be used in response to a button press event.
++       * The server may ignore move requests depending on the state of
++       * the surface (e.g. fullscreen or maximized).
++       * @param seat seat whose pointer is used
++       * @param serial serial number of the implicit grab on the pointer
++       */
++      void (*move)(struct wl_client *client,
++                   struct wl_resource *resource,
++                   struct wl_resource *seat,
++                   uint32_t serial);
++      /**
++       * start an interactive resize
++       *
++       * Start a pointer-driven resizing of the surface.
++       *
++       * This request must be used in response to a button press event.
++       * The server may ignore resize requests depending on the state of
++       * the surface (e.g. fullscreen or maximized).
++       * @param seat seat whose pointer is used
++       * @param serial serial number of the implicit grab on the pointer
++       * @param edges which edge or corner is being dragged
++       */
++      void (*resize)(struct wl_client *client,
++                     struct wl_resource *resource,
++                     struct wl_resource *seat,
++                     uint32_t serial,
++                     uint32_t edges);
++      /**
++       * make the surface a toplevel surface
++       *
++       * Map the surface as a toplevel surface.
++       *
++       * A toplevel surface is not fullscreen, maximized or transient.
++       */
++      void (*set_toplevel)(struct wl_client *client,
++                           struct wl_resource *resource);
++      /**
++       * make the surface a transient surface
++       *
++       * Map the surface relative to an existing surface.
++       *
++       * The x and y arguments specify the location of the upper left
++       * corner of the surface relative to the upper left corner of the
++       * parent surface, in surface-local coordinates.
++       *
++       * The flags argument controls details of the transient behaviour.
++       * @param parent parent surface
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       * @param flags transient surface behavior
++       */
++      void (*set_transient)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            struct wl_resource *parent,
++                            int32_t x,
++                            int32_t y,
++                            uint32_t flags);
++      /**
++       * make the surface a fullscreen surface
++       *
++       * Map the surface as a fullscreen surface.
++       *
++       * If an output parameter is given then the surface will be made
++       * fullscreen on that output. If the client does not specify the
++       * output then the compositor will apply its policy - usually
++       * choosing the output on which the surface has the biggest surface
++       * area.
++       *
++       * The client may specify a method to resolve a size conflict
++       * between the output size and the surface size - this is provided
++       * through the method parameter.
++       *
++       * The framerate parameter is used only when the method is set to
++       * "driver", to indicate the preferred framerate. A value of 0
++       * indicates that the client does not care about framerate. The
++       * framerate is specified in mHz, that is framerate of 60000 is
++       * 60Hz.
++       *
++       * A method of "scale" or "driver" implies a scaling operation of
++       * the surface, either via a direct scaling operation or a change
++       * of the output mode. This will override any kind of output
++       * scaling, so that mapping a surface with a buffer size equal to
++       * the mode can fill the screen independent of buffer_scale.
++       *
++       * A method of "fill" means we don't scale up the buffer, however
++       * any output scale is applied. This means that you may run into an
++       * edge case where the application maps a buffer with the same size
++       * of the output mode but buffer_scale 1 (thus making a surface
++       * larger than the output). In this case it is allowed to downscale
++       * the results to fit the screen.
++       *
++       * The compositor must reply to this request with a configure event
++       * with the dimensions for the output on which the surface will be
++       * made fullscreen.
++       * @param method method for resolving size conflict
++       * @param framerate framerate in mHz
++       * @param output output on which the surface is to be fullscreen
++       */
++      void (*set_fullscreen)(struct wl_client *client,
++                             struct wl_resource *resource,
++                             uint32_t method,
++                             uint32_t framerate,
++                             struct wl_resource *output);
++      /**
++       * make the surface a popup surface
++       *
++       * Map the surface as a popup.
++       *
++       * A popup surface is a transient surface with an added pointer
++       * grab.
++       *
++       * An existing implicit grab will be changed to owner-events mode,
++       * and the popup grab will continue after the implicit grab ends
++       * (i.e. releasing the mouse button does not cause the popup to be
++       * unmapped).
++       *
++       * The popup grab continues until the window is destroyed or a
++       * mouse button is pressed in any other client's window. A click in
++       * any of the client's surfaces is reported as normal, however,
++       * clicks in other clients' surfaces will be discarded and trigger
++       * the callback.
++       *
++       * The x and y arguments specify the location of the upper left
++       * corner of the surface relative to the upper left corner of the
++       * parent surface, in surface-local coordinates.
++       * @param seat seat whose pointer is used
++       * @param serial serial number of the implicit grab on the pointer
++       * @param parent parent surface
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       * @param flags transient surface behavior
++       */
++      void (*set_popup)(struct wl_client *client,
++                        struct wl_resource *resource,
++                        struct wl_resource *seat,
++                        uint32_t serial,
++                        struct wl_resource *parent,
++                        int32_t x,
++                        int32_t y,
++                        uint32_t flags);
++      /**
++       * make the surface a maximized surface
++       *
++       * Map the surface as a maximized surface.
++       *
++       * If an output parameter is given then the surface will be
++       * maximized on that output. If the client does not specify the
++       * output then the compositor will apply its policy - usually
++       * choosing the output on which the surface has the biggest surface
++       * area.
++       *
++       * The compositor will reply with a configure event telling the
++       * expected new surface size. The operation is completed on the
++       * next buffer attach to this surface.
++       *
++       * A maximized surface typically fills the entire output it is
++       * bound to, except for desktop elements such as panels. This is
++       * the main difference between a maximized shell surface and a
++       * fullscreen shell surface.
++       *
++       * The details depend on the compositor implementation.
++       * @param output output on which the surface is to be maximized
++       */
++      void (*set_maximized)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            struct wl_resource *output);
++      /**
++       * set surface title
++       *
++       * Set a short title for the surface.
++       *
++       * This string may be used to identify the surface in a task bar,
++       * window list, or other user interface elements provided by the
++       * compositor.
++       *
++       * The string must be encoded in UTF-8.
++       * @param title surface title
++       */
++      void (*set_title)(struct wl_client *client,
++                        struct wl_resource *resource,
++                        const char *title);
++      /**
++       * set surface class
++       *
++       * Set a class for the surface.
++       *
++       * The surface class identifies the general class of applications
++       * to which the surface belongs. A common convention is to use the
++       * file name (or the full path if it is a non-standard location) of
++       * the application's .desktop file as the class.
++       * @param class_ surface class
++       */
++      void (*set_class)(struct wl_client *client,
++                        struct wl_resource *resource,
++                        const char *class_);
++};
++
++#define WL_SHELL_SURFACE_PING 0
++#define WL_SHELL_SURFACE_CONFIGURE 1
++#define WL_SHELL_SURFACE_POPUP_DONE 2
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PING_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_CONFIGURE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_POPUP_DONE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_PONG_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_MOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_RESIZE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TOPLEVEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TRANSIENT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_FULLSCREEN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_POPUP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_MAXIMIZED_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_TITLE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_shell_surface
++ */
++#define WL_SHELL_SURFACE_SET_CLASS_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an ping event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the ping
++ */
++static inline void
++wl_shell_surface_send_ping(struct wl_resource *resource_, uint32_t serial)
++{
++      wl_resource_post_event(resource_, WL_SHELL_SURFACE_PING, serial);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an configure event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param edges how the surface was resized
++ * @param width new width of the surface
++ * @param height new height of the surface
++ */
++static inline void
++wl_shell_surface_send_configure(struct wl_resource *resource_, uint32_t edges, int32_t width, int32_t height)
++{
++      wl_resource_post_event(resource_, WL_SHELL_SURFACE_CONFIGURE, edges, width, height);
++}
++
++/**
++ * @ingroup iface_wl_shell_surface
++ * Sends an popup_done event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_shell_surface_send_popup_done(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_SHELL_SURFACE_POPUP_DONE);
++}
++
++#ifndef WL_SURFACE_ERROR_ENUM
++#define WL_SURFACE_ERROR_ENUM
++/**
++ * @ingroup iface_wl_surface
++ * wl_surface error values
++ *
++ * These errors can be emitted in response to wl_surface requests.
++ */
++enum wl_surface_error {
++      /**
++       * buffer scale value is invalid
++       */
++      WL_SURFACE_ERROR_INVALID_SCALE = 0,
++      /**
++       * buffer transform value is invalid
++       */
++      WL_SURFACE_ERROR_INVALID_TRANSFORM = 1,
++};
++#endif /* WL_SURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_surface
++ * @struct wl_surface_interface
++ */
++struct wl_surface_interface {
++      /**
++       * delete surface
++       *
++       * Deletes the surface and invalidates its object ID.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * set the surface contents
++       *
++       * Set a buffer as the content of this surface.
++       *
++       * The new size of the surface is calculated based on the buffer
++       * size transformed by the inverse buffer_transform and the inverse
++       * buffer_scale. This means that the supplied buffer must be an
++       * integer multiple of the buffer_scale.
++       *
++       * The x and y arguments specify the location of the new pending
++       * buffer's upper left corner, relative to the current buffer's
++       * upper left corner, in surface-local coordinates. In other words,
++       * the x and y, combined with the new surface size define in which
++       * directions the surface's size changes.
++       *
++       * Surface contents are double-buffered state, see
++       * wl_surface.commit.
++       *
++       * The initial surface contents are void; there is no content.
++       * wl_surface.attach assigns the given wl_buffer as the pending
++       * wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++       * surface contents, and the size of the surface becomes the size
++       * calculated from the wl_buffer, as described above. After commit,
++       * there is no pending buffer until the next attach.
++       *
++       * Committing a pending wl_buffer allows the compositor to read the
++       * pixels in the wl_buffer. The compositor may access the pixels at
++       * any time after the wl_surface.commit request. When the
++       * compositor will not access the pixels anymore, it will send the
++       * wl_buffer.release event. Only after receiving wl_buffer.release,
++       * the client may reuse the wl_buffer. A wl_buffer that has been
++       * attached and then replaced by another attach instead of
++       * committed will not receive a release event, and is not used by
++       * the compositor.
++       *
++       * Destroying the wl_buffer after wl_buffer.release does not change
++       * the surface contents. However, if the client destroys the
++       * wl_buffer before receiving the wl_buffer.release event, the
++       * surface contents become undefined immediately.
++       *
++       * If wl_surface.attach is sent with a NULL wl_buffer, the
++       * following wl_surface.commit will remove the surface content.
++       * @param buffer buffer of surface contents
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       */
++      void (*attach)(struct wl_client *client,
++                     struct wl_resource *resource,
++                     struct wl_resource *buffer,
++                     int32_t x,
++                     int32_t y);
++      /**
++       * mark part of the surface damaged
++       *
++       * This request is used to describe the regions where the pending
++       * buffer is different from the current surface contents, and where
++       * the surface therefore needs to be repainted. The compositor
++       * ignores the parts of the damage that fall outside of the
++       * surface.
++       *
++       * Damage is double-buffered state, see wl_surface.commit.
++       *
++       * The damage rectangle is specified in surface-local coordinates,
++       * where x and y specify the upper left corner of the damage
++       * rectangle.
++       *
++       * The initial value for pending damage is empty: no damage.
++       * wl_surface.damage adds pending damage: the new pending damage is
++       * the union of old pending damage and the given rectangle.
++       *
++       * wl_surface.commit assigns pending damage as the current damage,
++       * and clears pending damage. The server will clear the current
++       * damage as it repaints the surface.
++       *
++       * Alternatively, damage can be posted with
++       * wl_surface.damage_buffer which uses buffer coordinates instead
++       * of surface coordinates, and is probably the preferred and
++       * intuitive way of doing this.
++       * @param x surface-local x coordinate
++       * @param y surface-local y coordinate
++       * @param width width of damage rectangle
++       * @param height height of damage rectangle
++       */
++      void (*damage)(struct wl_client *client,
++                     struct wl_resource *resource,
++                     int32_t x,
++                     int32_t y,
++                     int32_t width,
++                     int32_t height);
++      /**
++       * request a frame throttling hint
++       *
++       * Request a notification when it is a good time to start drawing
++       * a new frame, by creating a frame callback. This is useful for
++       * throttling redrawing operations, and driving animations.
++       *
++       * When a client is animating on a wl_surface, it can use the
++       * 'frame' request to get notified when it is a good time to draw
++       * and commit the next frame of animation. If the client commits an
++       * update earlier than that, it is likely that some updates will
++       * not make it to the display, and the client is wasting resources
++       * by drawing too often.
++       *
++       * The frame request will take effect on the next
++       * wl_surface.commit. The notification will only be posted for one
++       * frame unless requested again. For a wl_surface, the
++       * notifications are posted in the order the frame requests were
++       * committed.
++       *
++       * The server must send the notifications so that a client will not
++       * send excessive updates, while still allowing the highest
++       * possible update rate for clients that wait for the reply before
++       * drawing again. The server should give some time for the client
++       * to draw and commit after sending the frame callback events to
++       * let it hit the next output refresh.
++       *
++       * A server should avoid signaling the frame callbacks if the
++       * surface is not visible in any way, e.g. the surface is
++       * off-screen, or completely obscured by other opaque surfaces.
++       *
++       * The object returned by this request will be destroyed by the
++       * compositor after the callback is fired and as such the client
++       * must not attempt to use it after that point.
++       *
++       * The callback_data passed in the callback is the current time, in
++       * milliseconds, with an undefined base.
++       * @param callback callback object for the frame request
++       */
++      void (*frame)(struct wl_client *client,
++                    struct wl_resource *resource,
++                    uint32_t callback);
++      /**
++       * set opaque region
++       *
++       * This request sets the region of the surface that contains
++       * opaque content.
++       *
++       * The opaque region is an optimization hint for the compositor
++       * that lets it optimize the redrawing of content behind opaque
++       * regions. Setting an opaque region is not required for correct
++       * behaviour, but marking transparent content as opaque will result
++       * in repaint artifacts.
++       *
++       * The opaque region is specified in surface-local coordinates.
++       *
++       * The compositor ignores the parts of the opaque region that fall
++       * outside of the surface.
++       *
++       * Opaque region is double-buffered state, see wl_surface.commit.
++       *
++       * wl_surface.set_opaque_region changes the pending opaque region.
++       * wl_surface.commit copies the pending region to the current
++       * region. Otherwise, the pending and current regions are never
++       * changed.
++       *
++       * The initial value for an opaque region is empty. Setting the
++       * pending opaque region has copy semantics, and the wl_region
++       * object can be destroyed immediately. A NULL wl_region causes the
++       * pending opaque region to be set to empty.
++       * @param region opaque region of the surface
++       */
++      void (*set_opaque_region)(struct wl_client *client,
++                                struct wl_resource *resource,
++                                struct wl_resource *region);
++      /**
++       * set input region
++       *
++       * This request sets the region of the surface that can receive
++       * pointer and touch events.
++       *
++       * Input events happening outside of this region will try the next
++       * surface in the server surface stack. The compositor ignores the
++       * parts of the input region that fall outside of the surface.
++       *
++       * The input region is specified in surface-local coordinates.
++       *
++       * Input region is double-buffered state, see wl_surface.commit.
++       *
++       * wl_surface.set_input_region changes the pending input region.
++       * wl_surface.commit copies the pending region to the current
++       * region. Otherwise the pending and current regions are never
++       * changed, except cursor and icon surfaces are special cases, see
++       * wl_pointer.set_cursor and wl_data_device.start_drag.
++       *
++       * The initial value for an input region is infinite. That means
++       * the whole surface will accept input. Setting the pending input
++       * region has copy semantics, and the wl_region object can be
++       * destroyed immediately. A NULL wl_region causes the input region
++       * to be set to infinite.
++       * @param region input region of the surface
++       */
++      void (*set_input_region)(struct wl_client *client,
++                               struct wl_resource *resource,
++                               struct wl_resource *region);
++      /**
++       * commit pending surface state
++       *
++       * Surface state (input, opaque, and damage regions, attached
++       * buffers, etc.) is double-buffered. Protocol requests modify the
++       * pending state, as opposed to the current state in use by the
++       * compositor. A commit request atomically applies all pending
++       * state, replacing the current state. After commit, the new
++       * pending state is as documented for each related request.
++       *
++       * On commit, a pending wl_buffer is applied first, and all other
++       * state second. This means that all coordinates in double-buffered
++       * state are relative to the new wl_buffer coming into use, except
++       * for wl_surface.attach itself. If there is no pending wl_buffer,
++       * the coordinates are relative to the current surface contents.
++       *
++       * All requests that need a commit to become effective are
++       * documented to affect double-buffered state.
++       *
++       * Other interfaces may add further double-buffered surface state.
++       */
++      void (*commit)(struct wl_client *client,
++                     struct wl_resource *resource);
++      /**
++       * sets the buffer transformation
++       *
++       * This request sets an optional transformation on how the
++       * compositor interprets the contents of the buffer attached to the
++       * surface. The accepted values for the transform parameter are the
++       * values for wl_output.transform.
++       *
++       * Buffer transform is double-buffered state, see
++       * wl_surface.commit.
++       *
++       * A newly created surface has its buffer transformation set to
++       * normal.
++       *
++       * wl_surface.set_buffer_transform changes the pending buffer
++       * transformation. wl_surface.commit copies the pending buffer
++       * transformation to the current one. Otherwise, the pending and
++       * current values are never changed.
++       *
++       * The purpose of this request is to allow clients to render
++       * content according to the output transform, thus permitting the
++       * compositor to use certain optimizations even if the display is
++       * rotated. Using hardware overlays and scanning out a client
++       * buffer for fullscreen surfaces are examples of such
++       * optimizations. Those optimizations are highly dependent on the
++       * compositor implementation, so the use of this request should be
++       * considered on a case-by-case basis.
++       *
++       * Note that if the transform value includes 90 or 270 degree
++       * rotation, the width of the buffer will become the surface height
++       * and the height of the buffer will become the surface width.
++       *
++       * If transform is not one of the values from the
++       * wl_output.transform enum the invalid_transform protocol error is
++       * raised.
++       * @param transform transform for interpreting buffer contents
++       * @since 2
++       */
++      void (*set_buffer_transform)(struct wl_client *client,
++                                   struct wl_resource *resource,
++                                   int32_t transform);
++      /**
++       * sets the buffer scaling factor
++       *
++       * This request sets an optional scaling factor on how the
++       * compositor interprets the contents of the buffer attached to the
++       * window.
++       *
++       * Buffer scale is double-buffered state, see wl_surface.commit.
++       *
++       * A newly created surface has its buffer scale set to 1.
++       *
++       * wl_surface.set_buffer_scale changes the pending buffer scale.
++       * wl_surface.commit copies the pending buffer scale to the current
++       * one. Otherwise, the pending and current values are never
++       * changed.
++       *
++       * The purpose of this request is to allow clients to supply higher
++       * resolution buffer data for use on high resolution outputs. It is
++       * intended that you pick the same buffer scale as the scale of the
++       * output that the surface is displayed on. This means the
++       * compositor can avoid scaling when rendering the surface on that
++       * output.
++       *
++       * Note that if the scale is larger than 1, then you have to attach
++       * a buffer that is larger (by a factor of scale in each dimension)
++       * than the desired surface size.
++       *
++       * If scale is not positive the invalid_scale protocol error is
++       * raised.
++       * @param scale positive scale for interpreting buffer contents
++       * @since 3
++       */
++      void (*set_buffer_scale)(struct wl_client *client,
++                               struct wl_resource *resource,
++                               int32_t scale);
++      /**
++       * mark part of the surface damaged using buffer coordinates
++       *
++       * This request is used to describe the regions where the pending
++       * buffer is different from the current surface contents, and where
++       * the surface therefore needs to be repainted. The compositor
++       * ignores the parts of the damage that fall outside of the
++       * surface.
++       *
++       * Damage is double-buffered state, see wl_surface.commit.
++       *
++       * The damage rectangle is specified in buffer coordinates, where x
++       * and y specify the upper left corner of the damage rectangle.
++       *
++       * The initial value for pending damage is empty: no damage.
++       * wl_surface.damage_buffer adds pending damage: the new pending
++       * damage is the union of old pending damage and the given
++       * rectangle.
++       *
++       * wl_surface.commit assigns pending damage as the current damage,
++       * and clears pending damage. The server will clear the current
++       * damage as it repaints the surface.
++       *
++       * This request differs from wl_surface.damage in only one way - it
++       * takes damage in buffer coordinates instead of surface-local
++       * coordinates. While this generally is more intuitive than surface
++       * coordinates, it is especially desirable when using wp_viewport
++       * or when a drawing library (like EGL) is unaware of buffer scale
++       * and buffer transform.
++       *
++       * Note: Because buffer transformation changes and damage requests
++       * may be interleaved in the protocol stream, it is impossible to
++       * determine the actual mapping between surface and buffer damage
++       * until wl_surface.commit time. Therefore, compositors wishing to
++       * take both kinds of damage into account will have to accumulate
++       * damage from the two requests separately and only transform from
++       * one to the other after receiving the wl_surface.commit.
++       * @param x buffer-local x coordinate
++       * @param y buffer-local y coordinate
++       * @param width width of damage rectangle
++       * @param height height of damage rectangle
++       * @since 4
++       */
++      void (*damage_buffer)(struct wl_client *client,
++                            struct wl_resource *resource,
++                            int32_t x,
++                            int32_t y,
++                            int32_t width,
++                            int32_t height);
++};
++
++#define WL_SURFACE_ENTER 0
++#define WL_SURFACE_LEAVE 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_LEAVE_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_ATTACH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_OPAQUE_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_INPUT_REGION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_COMMIT_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_TRANSFORM_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION 3
++/**
++ * @ingroup iface_wl_surface
++ */
++#define WL_SURFACE_DAMAGE_BUFFER_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_surface
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param output output entered by the surface
++ */
++static inline void
++wl_surface_send_enter(struct wl_resource *resource_, struct wl_resource *output)
++{
++      wl_resource_post_event(resource_, WL_SURFACE_ENTER, output);
++}
++
++/**
++ * @ingroup iface_wl_surface
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param output output left by the surface
++ */
++static inline void
++wl_surface_send_leave(struct wl_resource *resource_, struct wl_resource *output)
++{
++      wl_resource_post_event(resource_, WL_SURFACE_LEAVE, output);
++}
++
++#ifndef WL_SEAT_CAPABILITY_ENUM
++#define WL_SEAT_CAPABILITY_ENUM
++/**
++ * @ingroup iface_wl_seat
++ * seat capability bitmask
++ *
++ * This is a bitmask of capabilities this seat has; if a member is
++ * set, then it is present on the seat.
++ */
++enum wl_seat_capability {
++      /**
++       * the seat has pointer devices
++       */
++      WL_SEAT_CAPABILITY_POINTER = 1,
++      /**
++       * the seat has one or more keyboards
++       */
++      WL_SEAT_CAPABILITY_KEYBOARD = 2,
++      /**
++       * the seat has touch devices
++       */
++      WL_SEAT_CAPABILITY_TOUCH = 4,
++};
++#endif /* WL_SEAT_CAPABILITY_ENUM */
++
++/**
++ * @ingroup iface_wl_seat
++ * @struct wl_seat_interface
++ */
++struct wl_seat_interface {
++      /**
++       * return pointer object
++       *
++       * The ID provided will be initialized to the wl_pointer
++       * interface for this seat.
++       *
++       * This request only takes effect if the seat has the pointer
++       * capability, or has had the pointer capability in the past. It is
++       * a protocol violation to issue this request on a seat that has
++       * never had the pointer capability.
++       * @param id seat pointer
++       */
++      void (*get_pointer)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          uint32_t id);
++      /**
++       * return keyboard object
++       *
++       * The ID provided will be initialized to the wl_keyboard
++       * interface for this seat.
++       *
++       * This request only takes effect if the seat has the keyboard
++       * capability, or has had the keyboard capability in the past. It
++       * is a protocol violation to issue this request on a seat that has
++       * never had the keyboard capability.
++       * @param id seat keyboard
++       */
++      void (*get_keyboard)(struct wl_client *client,
++                           struct wl_resource *resource,
++                           uint32_t id);
++      /**
++       * return touch object
++       *
++       * The ID provided will be initialized to the wl_touch interface
++       * for this seat.
++       *
++       * This request only takes effect if the seat has the touch
++       * capability, or has had the touch capability in the past. It is a
++       * protocol violation to issue this request on a seat that has
++       * never had the touch capability.
++       * @param id seat touch interface
++       */
++      void (*get_touch)(struct wl_client *client,
++                        struct wl_resource *resource,
++                        uint32_t id);
++      /**
++       * release the seat object
++       *
++       * Using this request a client can tell the server that it is not
++       * going to use the seat object anymore.
++       * @since 5
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_SEAT_CAPABILITIES 0
++#define WL_SEAT_NAME 1
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_CAPABILITIES_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_NAME_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_POINTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_KEYBOARD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_GET_TOUCH_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_seat
++ */
++#define WL_SEAT_RELEASE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_seat
++ * Sends an capabilities event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param capabilities capabilities of the seat
++ */
++static inline void
++wl_seat_send_capabilities(struct wl_resource *resource_, uint32_t capabilities)
++{
++      wl_resource_post_event(resource_, WL_SEAT_CAPABILITIES, capabilities);
++}
++
++/**
++ * @ingroup iface_wl_seat
++ * Sends an name event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param name seat identifier
++ */
++static inline void
++wl_seat_send_name(struct wl_resource *resource_, const char *name)
++{
++      wl_resource_post_event(resource_, WL_SEAT_NAME, name);
++}
++
++#ifndef WL_POINTER_ERROR_ENUM
++#define WL_POINTER_ERROR_ENUM
++enum wl_pointer_error {
++      /**
++       * given wl_surface has another role
++       */
++      WL_POINTER_ERROR_ROLE = 0,
++};
++#endif /* WL_POINTER_ERROR_ENUM */
++
++#ifndef WL_POINTER_BUTTON_STATE_ENUM
++#define WL_POINTER_BUTTON_STATE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * physical button state
++ *
++ * Describes the physical state of a button that produced the button
++ * event.
++ */
++enum wl_pointer_button_state {
++      /**
++       * the button is not pressed
++       */
++      WL_POINTER_BUTTON_STATE_RELEASED = 0,
++      /**
++       * the button is pressed
++       */
++      WL_POINTER_BUTTON_STATE_PRESSED = 1,
++};
++#endif /* WL_POINTER_BUTTON_STATE_ENUM */
++
++#ifndef WL_POINTER_AXIS_ENUM
++#define WL_POINTER_AXIS_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis types
++ *
++ * Describes the axis types of scroll events.
++ */
++enum wl_pointer_axis {
++      /**
++       * vertical axis
++       */
++      WL_POINTER_AXIS_VERTICAL_SCROLL = 0,
++      /**
++       * horizontal axis
++       */
++      WL_POINTER_AXIS_HORIZONTAL_SCROLL = 1,
++};
++#endif /* WL_POINTER_AXIS_ENUM */
++
++#ifndef WL_POINTER_AXIS_SOURCE_ENUM
++#define WL_POINTER_AXIS_SOURCE_ENUM
++/**
++ * @ingroup iface_wl_pointer
++ * axis source types
++ *
++ * Describes the source types for axis events. This indicates to the
++ * client how an axis event was physically generated; a client may
++ * adjust the user interface accordingly. For example, scroll events
++ * from a "finger" source may be in a smooth coordinate space with
++ * kinetic scrolling whereas a "wheel" source may be in discrete steps
++ * of a number of lines.
++ */
++enum wl_pointer_axis_source {
++      /**
++       * a physical wheel rotation
++       */
++      WL_POINTER_AXIS_SOURCE_WHEEL = 0,
++      /**
++       * finger on a touch surface
++       */
++      WL_POINTER_AXIS_SOURCE_FINGER = 1,
++      /**
++       * continuous coordinate space
++       *
++       * A device generating events in a continuous coordinate space,
++       * but using something other than a finger. One example for this
++       * source is button-based scrolling where the vertical motion of a
++       * device is converted to scroll events while a button is held
++       * down.
++       */
++      WL_POINTER_AXIS_SOURCE_CONTINUOUS = 2,
++      /**
++       * a physical wheel tilt
++       *
++       * Indicates that the actual device is a wheel but the scroll
++       * event is not caused by a rotation but a (usually sideways) tilt
++       * of the wheel.
++       * @since 6
++       */
++      WL_POINTER_AXIS_SOURCE_WHEEL_TILT = 3,
++};
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_WHEEL_TILT_SINCE_VERSION 6
++#endif /* WL_POINTER_AXIS_SOURCE_ENUM */
++
++/**
++ * @ingroup iface_wl_pointer
++ * @struct wl_pointer_interface
++ */
++struct wl_pointer_interface {
++      /**
++       * set the pointer surface
++       *
++       * Set the pointer surface, i.e., the surface that contains the
++       * pointer image (cursor). This request gives the surface the role
++       * of a cursor. If the surface already has another role, it raises
++       * a protocol error.
++       *
++       * The cursor actually changes only if the pointer focus for this
++       * device is one of the requesting client's surfaces or the surface
++       * parameter is the current pointer surface. If there was a
++       * previous surface set with this request it is replaced. If
++       * surface is NULL, the pointer image is hidden.
++       *
++       * The parameters hotspot_x and hotspot_y define the position of
++       * the pointer surface relative to the pointer location. Its
++       * top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++       * where (x, y) are the coordinates of the pointer location, in
++       * surface-local coordinates.
++       *
++       * On surface.attach requests to the pointer surface, hotspot_x and
++       * hotspot_y are decremented by the x and y parameters passed to
++       * the request. Attach must be confirmed by wl_surface.commit as
++       * usual.
++       *
++       * The hotspot can also be updated by passing the currently set
++       * pointer surface to this request with new values for hotspot_x
++       * and hotspot_y.
++       *
++       * The current and pending input regions of the wl_surface are
++       * cleared, and wl_surface.set_input_region is ignored until the
++       * wl_surface is no longer used as the cursor. When the use as a
++       * cursor ends, the current and pending input regions become
++       * undefined, and the wl_surface is unmapped.
++       * @param serial serial number of the enter event
++       * @param surface pointer surface
++       * @param hotspot_x surface-local x coordinate
++       * @param hotspot_y surface-local y coordinate
++       */
++      void (*set_cursor)(struct wl_client *client,
++                         struct wl_resource *resource,
++                         uint32_t serial,
++                         struct wl_resource *surface,
++                         int32_t hotspot_x,
++                         int32_t hotspot_y);
++      /**
++       * release the pointer object
++       *
++       * Using this request a client can tell the server that it is not
++       * going to use the pointer object anymore.
++       *
++       * This request destroys the pointer proxy object, so clients must
++       * not call wl_pointer_destroy() after using this request.
++       * @since 3
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_POINTER_ENTER 0
++#define WL_POINTER_LEAVE 1
++#define WL_POINTER_MOTION 2
++#define WL_POINTER_BUTTON 3
++#define WL_POINTER_AXIS 4
++#define WL_POINTER_FRAME 5
++#define WL_POINTER_AXIS_SOURCE 6
++#define WL_POINTER_AXIS_STOP 7
++#define WL_POINTER_AXIS_DISCRETE 8
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_BUTTON_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_FRAME_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_SOURCE_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_STOP_SINCE_VERSION 5
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_AXIS_DISCRETE_SINCE_VERSION 5
++
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_SET_CURSOR_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_pointer
++ */
++#define WL_POINTER_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface surface entered by the pointer
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++static inline void
++wl_pointer_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, wl_fixed_t surface_x, wl_fixed_t surface_y)
++{
++      wl_resource_post_event(resource_, WL_POINTER_ENTER, serial, surface, surface_x, surface_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the leave event
++ * @param surface surface left by the pointer
++ */
++static inline void
++wl_pointer_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface)
++{
++      wl_resource_post_event(resource_, WL_POINTER_LEAVE, serial, surface);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param surface_x surface-local x coordinate
++ * @param surface_y surface-local y coordinate
++ */
++static inline void
++wl_pointer_send_motion(struct wl_resource *resource_, uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
++{
++      wl_resource_post_event(resource_, WL_POINTER_MOTION, time, surface_x, surface_y);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an button event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the button event
++ * @param time timestamp with millisecond granularity
++ * @param button button that produced the event
++ * @param state physical state of the button
++ */
++static inline void
++wl_pointer_send_button(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
++{
++      wl_resource_post_event(resource_, WL_POINTER_BUTTON, serial, time, button, state);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param axis axis type
++ * @param value length of vector in surface-local coordinate space
++ */
++static inline void
++wl_pointer_send_axis(struct wl_resource *resource_, uint32_t time, uint32_t axis, wl_fixed_t value)
++{
++      wl_resource_post_event(resource_, WL_POINTER_AXIS, time, axis, value);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an frame event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_pointer_send_frame(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_POINTER_FRAME);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_source event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param axis_source source of the axis event
++ */
++static inline void
++wl_pointer_send_axis_source(struct wl_resource *resource_, uint32_t axis_source)
++{
++      wl_resource_post_event(resource_, WL_POINTER_AXIS_SOURCE, axis_source);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_stop event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param axis the axis stopped with this event
++ */
++static inline void
++wl_pointer_send_axis_stop(struct wl_resource *resource_, uint32_t time, uint32_t axis)
++{
++      wl_resource_post_event(resource_, WL_POINTER_AXIS_STOP, time, axis);
++}
++
++/**
++ * @ingroup iface_wl_pointer
++ * Sends an axis_discrete event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param axis axis type
++ * @param discrete number of steps
++ */
++static inline void
++wl_pointer_send_axis_discrete(struct wl_resource *resource_, uint32_t axis, int32_t discrete)
++{
++      wl_resource_post_event(resource_, WL_POINTER_AXIS_DISCRETE, axis, discrete);
++}
++
++#ifndef WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++#define WL_KEYBOARD_KEYMAP_FORMAT_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * keyboard mapping format
++ *
++ * This specifies the format of the keymap provided to the
++ * client with the wl_keyboard.keymap event.
++ */
++enum wl_keyboard_keymap_format {
++      /**
++       * no keymap; client must understand how to interpret the raw keycode
++       */
++      WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP = 0,
++      /**
++       * libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode
++       */
++      WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 = 1,
++};
++#endif /* WL_KEYBOARD_KEYMAP_FORMAT_ENUM */
++
++#ifndef WL_KEYBOARD_KEY_STATE_ENUM
++#define WL_KEYBOARD_KEY_STATE_ENUM
++/**
++ * @ingroup iface_wl_keyboard
++ * physical key state
++ *
++ * Describes the physical state of a key that produced the key event.
++ */
++enum wl_keyboard_key_state {
++      /**
++       * key is not pressed
++       */
++      WL_KEYBOARD_KEY_STATE_RELEASED = 0,
++      /**
++       * key is pressed
++       */
++      WL_KEYBOARD_KEY_STATE_PRESSED = 1,
++};
++#endif /* WL_KEYBOARD_KEY_STATE_ENUM */
++
++/**
++ * @ingroup iface_wl_keyboard
++ * @struct wl_keyboard_interface
++ */
++struct wl_keyboard_interface {
++      /**
++       * release the keyboard object
++       *
++       * 
++       * @since 3
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_KEYBOARD_KEYMAP 0
++#define WL_KEYBOARD_ENTER 1
++#define WL_KEYBOARD_LEAVE 2
++#define WL_KEYBOARD_KEY 3
++#define WL_KEYBOARD_MODIFIERS 4
++#define WL_KEYBOARD_REPEAT_INFO 5
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEYMAP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_ENTER_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_LEAVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_KEY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_MODIFIERS_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION 4
++
++/**
++ * @ingroup iface_wl_keyboard
++ */
++#define WL_KEYBOARD_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an keymap event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param format keymap format
++ * @param fd keymap file descriptor
++ * @param size keymap size, in bytes
++ */
++static inline void
++wl_keyboard_send_keymap(struct wl_resource *resource_, uint32_t format, int32_t fd, uint32_t size)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_KEYMAP, format, fd, size);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an enter event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the enter event
++ * @param surface surface gaining keyboard focus
++ * @param keys the currently pressed keys
++ */
++static inline void
++wl_keyboard_send_enter(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface, struct wl_array *keys)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_ENTER, serial, surface, keys);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an leave event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the leave event
++ * @param surface surface that lost keyboard focus
++ */
++static inline void
++wl_keyboard_send_leave(struct wl_resource *resource_, uint32_t serial, struct wl_resource *surface)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_LEAVE, serial, surface);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an key event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the key event
++ * @param time timestamp with millisecond granularity
++ * @param key key that produced the event
++ * @param state physical state of the key
++ */
++static inline void
++wl_keyboard_send_key(struct wl_resource *resource_, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_KEY, serial, time, key, state);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an modifiers event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the modifiers event
++ * @param mods_depressed depressed modifiers
++ * @param mods_latched latched modifiers
++ * @param mods_locked locked modifiers
++ * @param group keyboard layout
++ */
++static inline void
++wl_keyboard_send_modifiers(struct wl_resource *resource_, uint32_t serial, uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_MODIFIERS, serial, mods_depressed, mods_latched, mods_locked, group);
++}
++
++/**
++ * @ingroup iface_wl_keyboard
++ * Sends an repeat_info event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param rate the rate of repeating keys in characters per second
++ * @param delay delay in milliseconds since key down until repeating starts
++ */
++static inline void
++wl_keyboard_send_repeat_info(struct wl_resource *resource_, int32_t rate, int32_t delay)
++{
++      wl_resource_post_event(resource_, WL_KEYBOARD_REPEAT_INFO, rate, delay);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * @struct wl_touch_interface
++ */
++struct wl_touch_interface {
++      /**
++       * release the touch object
++       *
++       * 
++       * @since 3
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_TOUCH_DOWN 0
++#define WL_TOUCH_UP 1
++#define WL_TOUCH_MOTION 2
++#define WL_TOUCH_FRAME 3
++#define WL_TOUCH_CANCEL 4
++#define WL_TOUCH_SHAPE 5
++#define WL_TOUCH_ORIENTATION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_DOWN_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_UP_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_MOTION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_FRAME_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_CANCEL_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_SHAPE_SINCE_VERSION 6
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_ORIENTATION_SINCE_VERSION 6
++
++/**
++ * @ingroup iface_wl_touch
++ */
++#define WL_TOUCH_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an down event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the touch down event
++ * @param time timestamp with millisecond granularity
++ * @param surface surface touched
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_touch_send_down(struct wl_resource *resource_, uint32_t serial, uint32_t time, struct wl_resource *surface, int32_t id, wl_fixed_t x, wl_fixed_t y)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_DOWN, serial, time, surface, id, x, y);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an up event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param serial serial number of the touch up event
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ */
++static inline void
++wl_touch_send_up(struct wl_resource *resource_, uint32_t serial, uint32_t time, int32_t id)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_UP, serial, time, id);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an motion event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param time timestamp with millisecond granularity
++ * @param id the unique ID of this touch point
++ * @param x surface-local x coordinate
++ * @param y surface-local y coordinate
++ */
++static inline void
++wl_touch_send_motion(struct wl_resource *resource_, uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_MOTION, time, id, x, y);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an frame event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_touch_send_frame(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_FRAME);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an cancel event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_touch_send_cancel(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_CANCEL);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an shape event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the unique ID of this touch point
++ * @param major length of the major axis in surface-local coordinates
++ * @param minor length of the minor axis in surface-local coordinates
++ */
++static inline void
++wl_touch_send_shape(struct wl_resource *resource_, int32_t id, wl_fixed_t major, wl_fixed_t minor)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_SHAPE, id, major, minor);
++}
++
++/**
++ * @ingroup iface_wl_touch
++ * Sends an orientation event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param id the unique ID of this touch point
++ * @param orientation angle between major axis and positive surface y-axis in degrees
++ */
++static inline void
++wl_touch_send_orientation(struct wl_resource *resource_, int32_t id, wl_fixed_t orientation)
++{
++      wl_resource_post_event(resource_, WL_TOUCH_ORIENTATION, id, orientation);
++}
++
++#ifndef WL_OUTPUT_SUBPIXEL_ENUM
++#define WL_OUTPUT_SUBPIXEL_ENUM
++/**
++ * @ingroup iface_wl_output
++ * subpixel geometry information
++ *
++ * This enumeration describes how the physical
++ * pixels on an output are laid out.
++ */
++enum wl_output_subpixel {
++      /**
++       * unknown geometry
++       */
++      WL_OUTPUT_SUBPIXEL_UNKNOWN = 0,
++      /**
++       * no geometry
++       */
++      WL_OUTPUT_SUBPIXEL_NONE = 1,
++      /**
++       * horizontal RGB
++       */
++      WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB = 2,
++      /**
++       * horizontal BGR
++       */
++      WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR = 3,
++      /**
++       * vertical RGB
++       */
++      WL_OUTPUT_SUBPIXEL_VERTICAL_RGB = 4,
++      /**
++       * vertical BGR
++       */
++      WL_OUTPUT_SUBPIXEL_VERTICAL_BGR = 5,
++};
++#endif /* WL_OUTPUT_SUBPIXEL_ENUM */
++
++#ifndef WL_OUTPUT_TRANSFORM_ENUM
++#define WL_OUTPUT_TRANSFORM_ENUM
++/**
++ * @ingroup iface_wl_output
++ * transform from framebuffer to output
++ *
++ * This describes the transform that a compositor will apply to a
++ * surface to compensate for the rotation or mirroring of an
++ * output device.
++ *
++ * The flipped values correspond to an initial flip around a
++ * vertical axis followed by rotation.
++ *
++ * The purpose is mainly to allow clients to render accordingly and
++ * tell the compositor, so that for fullscreen surfaces, the
++ * compositor will still be able to scan out directly from client
++ * surfaces.
++ */
++enum wl_output_transform {
++      /**
++       * no transform
++       */
++      WL_OUTPUT_TRANSFORM_NORMAL = 0,
++      /**
++       * 90 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_90 = 1,
++      /**
++       * 180 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_180 = 2,
++      /**
++       * 270 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_270 = 3,
++      /**
++       * 180 degree flip around a vertical axis
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED = 4,
++      /**
++       * flip and rotate 90 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_90 = 5,
++      /**
++       * flip and rotate 180 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_180 = 6,
++      /**
++       * flip and rotate 270 degrees counter-clockwise
++       */
++      WL_OUTPUT_TRANSFORM_FLIPPED_270 = 7,
++};
++#endif /* WL_OUTPUT_TRANSFORM_ENUM */
++
++#ifndef WL_OUTPUT_MODE_ENUM
++#define WL_OUTPUT_MODE_ENUM
++/**
++ * @ingroup iface_wl_output
++ * mode information
++ *
++ * These flags describe properties of an output mode.
++ * They are used in the flags bitfield of the mode event.
++ */
++enum wl_output_mode {
++      /**
++       * indicates this is the current mode
++       */
++      WL_OUTPUT_MODE_CURRENT = 0x1,
++      /**
++       * indicates this is the preferred mode
++       */
++      WL_OUTPUT_MODE_PREFERRED = 0x2,
++};
++#endif /* WL_OUTPUT_MODE_ENUM */
++
++/**
++ * @ingroup iface_wl_output
++ * @struct wl_output_interface
++ */
++struct wl_output_interface {
++      /**
++       * release the output object
++       *
++       * Using this request a client can tell the server that it is not
++       * going to use the output object anymore.
++       * @since 3
++       */
++      void (*release)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define WL_OUTPUT_GEOMETRY 0
++#define WL_OUTPUT_MODE 1
++#define WL_OUTPUT_DONE 2
++#define WL_OUTPUT_SCALE 3
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_GEOMETRY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_MODE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_DONE_SINCE_VERSION 2
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_SCALE_SINCE_VERSION 2
++
++/**
++ * @ingroup iface_wl_output
++ */
++#define WL_OUTPUT_RELEASE_SINCE_VERSION 3
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an geometry event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param x x position within the global compositor space
++ * @param y y position within the global compositor space
++ * @param physical_width width in millimeters of the output
++ * @param physical_height height in millimeters of the output
++ * @param subpixel subpixel orientation of the output
++ * @param make textual description of the manufacturer
++ * @param model textual description of the model
++ * @param transform transform that maps framebuffer to output
++ */
++static inline void
++wl_output_send_geometry(struct wl_resource *resource_, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char *make, const char *model, int32_t transform)
++{
++      wl_resource_post_event(resource_, WL_OUTPUT_GEOMETRY, x, y, physical_width, physical_height, subpixel, make, model, transform);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an mode event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param flags bitfield of mode flags
++ * @param width width of the mode in hardware units
++ * @param height height of the mode in hardware units
++ * @param refresh vertical refresh rate in mHz
++ */
++static inline void
++wl_output_send_mode(struct wl_resource *resource_, uint32_t flags, int32_t width, int32_t height, int32_t refresh)
++{
++      wl_resource_post_event(resource_, WL_OUTPUT_MODE, flags, width, height, refresh);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an done event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++wl_output_send_done(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, WL_OUTPUT_DONE);
++}
++
++/**
++ * @ingroup iface_wl_output
++ * Sends an scale event to the client owning the resource.
++ * @param resource_ The client's resource
++ * @param factor scaling factor of output
++ */
++static inline void
++wl_output_send_scale(struct wl_resource *resource_, int32_t factor)
++{
++      wl_resource_post_event(resource_, WL_OUTPUT_SCALE, factor);
++}
++
++/**
++ * @ingroup iface_wl_region
++ * @struct wl_region_interface
++ */
++struct wl_region_interface {
++      /**
++       * destroy region
++       *
++       * Destroy the region. This will invalidate the object ID.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * add rectangle to region
++       *
++       * Add the specified rectangle to the region.
++       * @param x region-local x coordinate
++       * @param y region-local y coordinate
++       * @param width rectangle width
++       * @param height rectangle height
++       */
++      void (*add)(struct wl_client *client,
++                  struct wl_resource *resource,
++                  int32_t x,
++                  int32_t y,
++                  int32_t width,
++                  int32_t height);
++      /**
++       * subtract rectangle from region
++       *
++       * Subtract the specified rectangle from the region.
++       * @param x region-local x coordinate
++       * @param y region-local y coordinate
++       * @param width rectangle width
++       * @param height rectangle height
++       */
++      void (*subtract)(struct wl_client *client,
++                       struct wl_resource *resource,
++                       int32_t x,
++                       int32_t y,
++                       int32_t width,
++                       int32_t height);
++};
++
++
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_ADD_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_region
++ */
++#define WL_REGION_SUBTRACT_SINCE_VERSION 1
++
++#ifndef WL_SUBCOMPOSITOR_ERROR_ENUM
++#define WL_SUBCOMPOSITOR_ERROR_ENUM
++enum wl_subcompositor_error {
++      /**
++       * the to-be sub-surface is invalid
++       */
++      WL_SUBCOMPOSITOR_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBCOMPOSITOR_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_subcompositor
++ * @struct wl_subcompositor_interface
++ */
++struct wl_subcompositor_interface {
++      /**
++       * unbind from the subcompositor interface
++       *
++       * Informs the server that the client will not be using this
++       * protocol object anymore. This does not affect any other objects,
++       * wl_subsurface objects included.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * give a surface the role sub-surface
++       *
++       * Create a sub-surface interface for the given surface, and
++       * associate it with the given parent surface. This turns a plain
++       * wl_surface into a sub-surface.
++       *
++       * The to-be sub-surface must not already have another role, and it
++       * must not have an existing wl_subsurface object. Otherwise a
++       * protocol error is raised.
++       * @param id the new sub-surface object ID
++       * @param surface the surface to be turned into a sub-surface
++       * @param parent the parent surface
++       */
++      void (*get_subsurface)(struct wl_client *client,
++                             struct wl_resource *resource,
++                             uint32_t id,
++                             struct wl_resource *surface,
++                             struct wl_resource *parent);
++};
++
++
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subcompositor
++ */
++#define WL_SUBCOMPOSITOR_GET_SUBSURFACE_SINCE_VERSION 1
++
++#ifndef WL_SUBSURFACE_ERROR_ENUM
++#define WL_SUBSURFACE_ERROR_ENUM
++enum wl_subsurface_error {
++      /**
++       * wl_surface is not a sibling or the parent
++       */
++      WL_SUBSURFACE_ERROR_BAD_SURFACE = 0,
++};
++#endif /* WL_SUBSURFACE_ERROR_ENUM */
++
++/**
++ * @ingroup iface_wl_subsurface
++ * @struct wl_subsurface_interface
++ */
++struct wl_subsurface_interface {
++      /**
++       * remove sub-surface interface
++       *
++       * The sub-surface interface is removed from the wl_surface
++       * object that was turned into a sub-surface with a
++       * wl_subcompositor.get_subsurface request. The wl_surface's
++       * association to the parent is deleted, and the wl_surface loses
++       * its role as a sub-surface. The wl_surface is unmapped.
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++      /**
++       * reposition the sub-surface
++       *
++       * This schedules a sub-surface position change. The sub-surface
++       * will be moved so that its origin (top left corner pixel) will be
++       * at the location x, y of the parent surface coordinate system.
++       * The coordinates are not restricted to the parent surface area.
++       * Negative values are allowed.
++       *
++       * The scheduled coordinates will take effect whenever the state of
++       * the parent surface is applied. When this happens depends on
++       * whether the parent surface is in synchronized mode or not. See
++       * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++       *
++       * If more than one set_position request is invoked by the client
++       * before the commit of the parent surface, the position of a new
++       * request always replaces the scheduled position from any previous
++       * request.
++       *
++       * The initial position is 0, 0.
++       * @param x x coordinate in the parent surface
++       * @param y y coordinate in the parent surface
++       */
++      void (*set_position)(struct wl_client *client,
++                           struct wl_resource *resource,
++                           int32_t x,
++                           int32_t y);
++      /**
++       * restack the sub-surface
++       *
++       * This sub-surface is taken from the stack, and put back just
++       * above the reference surface, changing the z-order of the
++       * sub-surfaces. The reference surface must be one of the sibling
++       * surfaces, or the parent surface. Using any other surface,
++       * including this sub-surface, will cause a protocol error.
++       *
++       * The z-order is double-buffered. Requests are handled in order
++       * and applied immediately to a pending state. The final pending
++       * state is copied to the active state the next time the state of
++       * the parent surface is applied. When this happens depends on
++       * whether the parent surface is in synchronized mode or not. See
++       * wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++       *
++       * A new sub-surface is initially added as the top-most in the
++       * stack of its siblings and parent.
++       * @param sibling the reference surface
++       */
++      void (*place_above)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          struct wl_resource *sibling);
++      /**
++       * restack the sub-surface
++       *
++       * The sub-surface is placed just below the reference surface.
++       * See wl_subsurface.place_above.
++       * @param sibling the reference surface
++       */
++      void (*place_below)(struct wl_client *client,
++                          struct wl_resource *resource,
++                          struct wl_resource *sibling);
++      /**
++       * set sub-surface to synchronized mode
++       *
++       * Change the commit behaviour of the sub-surface to synchronized
++       * mode, also described as the parent dependent mode.
++       *
++       * In synchronized mode, wl_surface.commit on a sub-surface will
++       * accumulate the committed state in a cache, but the state will
++       * not be applied and hence will not change the compositor output.
++       * The cached state is applied to the sub-surface immediately after
++       * the parent surface's state is applied. This ensures atomic
++       * updates of the parent and all its synchronized sub-surfaces.
++       * Applying the cached state will invalidate the cache, so further
++       * parent surface commits do not (re-)apply old state.
++       *
++       * See wl_subsurface for the recursive effect of this mode.
++       */
++      void (*set_sync)(struct wl_client *client,
++                       struct wl_resource *resource);
++      /**
++       * set sub-surface to desynchronized mode
++       *
++       * Change the commit behaviour of the sub-surface to
++       * desynchronized mode, also described as independent or freely
++       * running mode.
++       *
++       * In desynchronized mode, wl_surface.commit on a sub-surface will
++       * apply the pending state directly, without caching, as happens
++       * normally with a wl_surface. Calling wl_surface.commit on the
++       * parent surface has no effect on the sub-surface's wl_surface
++       * state. This mode allows a sub-surface to be updated on its own.
++       *
++       * If cached state exists when wl_surface.commit is called in
++       * desynchronized mode, the pending state is added to the cached
++       * state, and applied as a whole. This invalidates the cache.
++       *
++       * Note: even if a sub-surface is set to desynchronized, a parent
++       * sub-surface may override it to behave as synchronized. For
++       * details, see wl_subsurface.
++       *
++       * If a surface's parent surface behaves as desynchronized, then
++       * the cached state is applied on set_desync.
++       */
++      void (*set_desync)(struct wl_client *client,
++                         struct wl_resource *resource);
++};
++
++
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_DESTROY_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_POSITION_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_ABOVE_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_PLACE_BELOW_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_SYNC_SINCE_VERSION 1
++/**
++ * @ingroup iface_wl_subsurface
++ */
++#define WL_SUBSURFACE_SET_DESYNC_SINCE_VERSION 1
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2d769408803460415708a84c814b5a396eaf8bc6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,2748 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="wayland">
++
++  <copyright>
++    Copyright © 2008-2011 Kristian Høgsberg
++    Copyright © 2010-2011 Intel Corporation
++    Copyright © 2012-2013 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <interface name="wl_display" version="1">
++    <description summary="core global object">
++      The core global object.  This is a special singleton object.  It
++      is used for internal Wayland protocol features.
++    </description>
++
++    <request name="sync">
++      <description summary="asynchronous roundtrip">
++      The sync request asks the server to emit the 'done' event
++      on the returned wl_callback object.  Since requests are
++      handled in-order and events are delivered in-order, this can
++      be used as a barrier to ensure all previous requests and the
++      resulting events have been handled.
++
++      The object returned by this request will be destroyed by the
++      compositor after the callback is fired and as such the client must not
++      attempt to use it after that point.
++
++      The callback_data passed in the callback is the event serial.
++      </description>
++      <arg name="callback" type="new_id" interface="wl_callback"
++         summary="callback object for the sync request"/>
++    </request>
++
++    <request name="get_registry">
++      <description summary="get global registry object">
++      This request creates a registry object that allows the client
++      to list and bind the global objects available from the
++      compositor.
++      </description>
++      <arg name="registry" type="new_id" interface="wl_registry"
++         summary="global registry object"/>
++    </request>
++
++    <event name="error">
++      <description summary="fatal error event">
++      The error event is sent out when a fatal (non-recoverable)
++      error has occurred.  The object_id argument is the object
++      where the error occurred, most often in response to a request
++      to that object.  The code identifies the error and is defined
++      by the object interface.  As such, each interface defines its
++      own set of error codes.  The message is a brief description
++      of the error, for (debugging) convenience.
++      </description>
++      <arg name="object_id" type="object" summary="object where the error occurred"/>
++      <arg name="code" type="uint" summary="error code"/>
++      <arg name="message" type="string" summary="error description"/>
++    </event>
++
++    <enum name="error">
++      <description summary="global error values">
++      These errors are global and can be emitted in response to any
++      server request.
++      </description>
++      <entry name="invalid_object" value="0"
++           summary="server couldn't find object"/>
++      <entry name="invalid_method" value="1"
++           summary="method doesn't exist on the specified interface"/>
++      <entry name="no_memory" value="2"
++           summary="server is out of memory"/>
++    </enum>
++
++    <event name="delete_id">
++      <description summary="acknowledge object ID deletion">
++      This event is used internally by the object ID management
++      logic.  When a client deletes an object, the server will send
++      this event to acknowledge that it has seen the delete request.
++      When the client receives this event, it will know that it can
++      safely reuse the object ID.
++      </description>
++      <arg name="id" type="uint" summary="deleted object ID"/>
++    </event>
++  </interface>
++
++  <interface name="wl_registry" version="1">
++    <description summary="global registry object">
++      The singleton global registry object.  The server has a number of
++      global objects that are available to all clients.  These objects
++      typically represent an actual object in the server (for example,
++      an input device) or they are singleton objects that provide
++      extension functionality.
++
++      When a client creates a registry object, the registry object
++      will emit a global event for each global currently in the
++      registry.  Globals come and go as a result of device or
++      monitor hotplugs, reconfiguration or other events, and the
++      registry will send out global and global_remove events to
++      keep the client up to date with the changes.  To mark the end
++      of the initial burst of events, the client can use the
++      wl_display.sync request immediately after calling
++      wl_display.get_registry.
++
++      A client can bind to a global object by using the bind
++      request.  This creates a client-side handle that lets the object
++      emit events to the client and lets the client invoke requests on
++      the object.
++    </description>
++
++    <request name="bind">
++      <description summary="bind an object to the display">
++      Binds a new, client-created object to the server using the
++      specified name as the identifier.
++      </description>
++      <arg name="name" type="uint" summary="unique numeric name of the object"/>
++      <arg name="id" type="new_id" summary="bounded object"/>
++    </request>
++
++    <event name="global">
++      <description summary="announce global object">
++      Notify the client of global objects.
++
++      The event notifies the client that a global object with
++      the given name is now available, and it implements the
++      given version of the given interface.
++      </description>
++      <arg name="name" type="uint" summary="numeric name of the global object"/>
++      <arg name="interface" type="string" summary="interface implemented by the object"/>
++      <arg name="version" type="uint" summary="interface version"/>
++    </event>
++
++    <event name="global_remove">
++      <description summary="announce removal of global object">
++      Notify the client of removed global objects.
++
++      This event notifies the client that the global identified
++      by name is no longer available.  If the client bound to
++      the global using the bind request, the client should now
++      destroy that object.
++
++      The object remains valid and requests to the object will be
++      ignored until the client destroys it, to avoid races between
++      the global going away and a client sending a request to it.
++      </description>
++      <arg name="name" type="uint" summary="numeric name of the global object"/>
++    </event>
++  </interface>
++
++  <interface name="wl_callback" version="1">
++    <description summary="callback object">
++      Clients can handle the 'done' event to get notified when
++      the related request is done.
++    </description>
++
++    <event name="done">
++      <description summary="done event">
++      Notify the client when the related request is done.
++      </description>
++      <arg name="callback_data" type="uint" summary="request-specific data for the callback"/>
++    </event>
++  </interface>
++
++  <interface name="wl_compositor" version="4">
++    <description summary="the compositor singleton">
++      A compositor.  This object is a singleton global.  The
++      compositor is in charge of combining the contents of multiple
++      surfaces into one displayable output.
++    </description>
++
++    <request name="create_surface">
++      <description summary="create new surface">
++      Ask the compositor to create a new surface.
++      </description>
++      <arg name="id" type="new_id" interface="wl_surface" summary="the new surface"/>
++    </request>
++
++    <request name="create_region">
++      <description summary="create new region">
++      Ask the compositor to create a new region.
++      </description>
++      <arg name="id" type="new_id" interface="wl_region" summary="the new region"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shm_pool" version="1">
++    <description summary="a shared memory pool">
++      The wl_shm_pool object encapsulates a piece of memory shared
++      between the compositor and client.  Through the wl_shm_pool
++      object, the client can allocate shared memory wl_buffer objects.
++      All objects created through the same pool share the same
++      underlying mapped memory. Reusing the mapped memory avoids the
++      setup/teardown overhead and is useful when interactively resizing
++      a surface or for many small buffers.
++    </description>
++
++    <request name="create_buffer">
++      <description summary="create a buffer from the pool">
++      Create a wl_buffer object from the pool.
++
++      The buffer is created offset bytes into the pool and has
++      width and height as specified.  The stride argument specifies
++      the number of bytes from the beginning of one row to the beginning
++      of the next.  The format is the pixel format of the buffer and
++      must be one of those advertised through the wl_shm.format event.
++
++      A buffer will keep a reference to the pool it was created from
++      so it is valid to destroy the pool immediately after creating
++      a buffer from it.
++      </description>
++      <arg name="id" type="new_id" interface="wl_buffer" summary="buffer to create"/>
++      <arg name="offset" type="int" summary="buffer byte offset within the pool"/>
++      <arg name="width" type="int" summary="buffer width, in pixels"/>
++      <arg name="height" type="int" summary="buffer height, in pixels"/>
++      <arg name="stride" type="int" summary="number of bytes from the beginning of one row to the beginning of the next row"/>
++      <arg name="format" type="uint" enum="wl_shm.format" summary="buffer pixel format"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the pool">
++      Destroy the shared memory pool.
++
++      The mmapped memory will be released when all
++      buffers that have been created from this pool
++      are gone.
++      </description>
++    </request>
++
++    <request name="resize">
++      <description summary="change the size of the pool mapping">
++      This request will cause the server to remap the backing memory
++      for the pool from the file descriptor passed when the pool was
++      created, but using the new size.  This request can only be
++      used to make the pool bigger.
++      </description>
++      <arg name="size" type="int" summary="new size of the pool, in bytes"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shm" version="1">
++    <description summary="shared memory support">
++      A singleton global object that provides support for shared
++      memory.
++
++      Clients can create wl_shm_pool objects using the create_pool
++      request.
++
++      At connection setup time, the wl_shm object emits one or more
++      format events to inform clients about the valid pixel formats
++      that can be used for buffers.
++    </description>
++
++    <enum name="error">
++      <description summary="wl_shm error values">
++      These errors can be emitted in response to wl_shm requests.
++      </description>
++      <entry name="invalid_format" value="0" summary="buffer format is not known"/>
++      <entry name="invalid_stride" value="1" summary="invalid size or stride during pool or buffer creation"/>
++      <entry name="invalid_fd" value="2" summary="mmapping the file descriptor failed"/>
++    </enum>
++
++    <enum name="format">
++      <description summary="pixel formats">
++      This describes the memory layout of an individual pixel.
++
++      All renderers should support argb8888 and xrgb8888 but any other
++      formats are optional and may not be supported by the particular
++      renderer in use.
++
++      The drm format codes match the macros defined in drm_fourcc.h.
++      The formats actually supported by the compositor will be
++      reported by the format event.
++      </description>
++      <entry name="argb8888" value="0" summary="32-bit ARGB format, [31:0] A:R:G:B 8:8:8:8 little endian"/>
++      <entry name="xrgb8888" value="1" summary="32-bit RGB format, [31:0] x:R:G:B 8:8:8:8 little endian"/>
++      <entry name="c8" value="0x20203843" summary="8-bit color index format, [7:0] C"/>
++      <entry name="rgb332" value="0x38424752" summary="8-bit RGB format, [7:0] R:G:B 3:3:2"/>
++      <entry name="bgr233" value="0x38524742" summary="8-bit BGR format, [7:0] B:G:R 2:3:3"/>
++      <entry name="xrgb4444" value="0x32315258" summary="16-bit xRGB format, [15:0] x:R:G:B 4:4:4:4 little endian"/>
++      <entry name="xbgr4444" value="0x32314258" summary="16-bit xBGR format, [15:0] x:B:G:R 4:4:4:4 little endian"/>
++      <entry name="rgbx4444" value="0x32315852" summary="16-bit RGBx format, [15:0] R:G:B:x 4:4:4:4 little endian"/>
++      <entry name="bgrx4444" value="0x32315842" summary="16-bit BGRx format, [15:0] B:G:R:x 4:4:4:4 little endian"/>
++      <entry name="argb4444" value="0x32315241" summary="16-bit ARGB format, [15:0] A:R:G:B 4:4:4:4 little endian"/>
++      <entry name="abgr4444" value="0x32314241" summary="16-bit ABGR format, [15:0] A:B:G:R 4:4:4:4 little endian"/>
++      <entry name="rgba4444" value="0x32314152" summary="16-bit RBGA format, [15:0] R:G:B:A 4:4:4:4 little endian"/>
++      <entry name="bgra4444" value="0x32314142" summary="16-bit BGRA format, [15:0] B:G:R:A 4:4:4:4 little endian"/>
++      <entry name="xrgb1555" value="0x35315258" summary="16-bit xRGB format, [15:0] x:R:G:B 1:5:5:5 little endian"/>
++      <entry name="xbgr1555" value="0x35314258" summary="16-bit xBGR 1555 format, [15:0] x:B:G:R 1:5:5:5 little endian"/>
++      <entry name="rgbx5551" value="0x35315852" summary="16-bit RGBx 5551 format, [15:0] R:G:B:x 5:5:5:1 little endian"/>
++      <entry name="bgrx5551" value="0x35315842" summary="16-bit BGRx 5551 format, [15:0] B:G:R:x 5:5:5:1 little endian"/>
++      <entry name="argb1555" value="0x35315241" summary="16-bit ARGB 1555 format, [15:0] A:R:G:B 1:5:5:5 little endian"/>
++      <entry name="abgr1555" value="0x35314241" summary="16-bit ABGR 1555 format, [15:0] A:B:G:R 1:5:5:5 little endian"/>
++      <entry name="rgba5551" value="0x35314152" summary="16-bit RGBA 5551 format, [15:0] R:G:B:A 5:5:5:1 little endian"/>
++      <entry name="bgra5551" value="0x35314142" summary="16-bit BGRA 5551 format, [15:0] B:G:R:A 5:5:5:1 little endian"/>
++      <entry name="rgb565" value="0x36314752" summary="16-bit RGB 565 format, [15:0] R:G:B 5:6:5 little endian"/>
++      <entry name="bgr565" value="0x36314742" summary="16-bit BGR 565 format, [15:0] B:G:R 5:6:5 little endian"/>
++      <entry name="rgb888" value="0x34324752" summary="24-bit RGB format, [23:0] R:G:B little endian"/>
++      <entry name="bgr888" value="0x34324742" summary="24-bit BGR format, [23:0] B:G:R little endian"/>
++      <entry name="xbgr8888" value="0x34324258" summary="32-bit xBGR format, [31:0] x:B:G:R 8:8:8:8 little endian"/>
++      <entry name="rgbx8888" value="0x34325852" summary="32-bit RGBx format, [31:0] R:G:B:x 8:8:8:8 little endian"/>
++      <entry name="bgrx8888" value="0x34325842" summary="32-bit BGRx format, [31:0] B:G:R:x 8:8:8:8 little endian"/>
++      <entry name="abgr8888" value="0x34324241" summary="32-bit ABGR format, [31:0] A:B:G:R 8:8:8:8 little endian"/>
++      <entry name="rgba8888" value="0x34324152" summary="32-bit RGBA format, [31:0] R:G:B:A 8:8:8:8 little endian"/>
++      <entry name="bgra8888" value="0x34324142" summary="32-bit BGRA format, [31:0] B:G:R:A 8:8:8:8 little endian"/>
++      <entry name="xrgb2101010" value="0x30335258" summary="32-bit xRGB format, [31:0] x:R:G:B 2:10:10:10 little endian"/>
++      <entry name="xbgr2101010" value="0x30334258" summary="32-bit xBGR format, [31:0] x:B:G:R 2:10:10:10 little endian"/>
++      <entry name="rgbx1010102" value="0x30335852" summary="32-bit RGBx format, [31:0] R:G:B:x 10:10:10:2 little endian"/>
++      <entry name="bgrx1010102" value="0x30335842" summary="32-bit BGRx format, [31:0] B:G:R:x 10:10:10:2 little endian"/>
++      <entry name="argb2101010" value="0x30335241" summary="32-bit ARGB format, [31:0] A:R:G:B 2:10:10:10 little endian"/>
++      <entry name="abgr2101010" value="0x30334241" summary="32-bit ABGR format, [31:0] A:B:G:R 2:10:10:10 little endian"/>
++      <entry name="rgba1010102" value="0x30334152" summary="32-bit RGBA format, [31:0] R:G:B:A 10:10:10:2 little endian"/>
++      <entry name="bgra1010102" value="0x30334142" summary="32-bit BGRA format, [31:0] B:G:R:A 10:10:10:2 little endian"/>
++      <entry name="yuyv" value="0x56595559" summary="packed YCbCr format, [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian"/>
++      <entry name="yvyu" value="0x55595659" summary="packed YCbCr format, [31:0] Cb0:Y1:Cr0:Y0 8:8:8:8 little endian"/>
++      <entry name="uyvy" value="0x59565955" summary="packed YCbCr format, [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian"/>
++      <entry name="vyuy" value="0x59555956" summary="packed YCbCr format, [31:0] Y1:Cb0:Y0:Cr0 8:8:8:8 little endian"/>
++      <entry name="ayuv" value="0x56555941" summary="packed AYCbCr format, [31:0] A:Y:Cb:Cr 8:8:8:8 little endian"/>
++      <entry name="nv12" value="0x3231564e" summary="2 plane YCbCr Cr:Cb format, 2x2 subsampled Cr:Cb plane"/>
++      <entry name="nv21" value="0x3132564e" summary="2 plane YCbCr Cb:Cr format, 2x2 subsampled Cb:Cr plane"/>
++      <entry name="nv16" value="0x3631564e" summary="2 plane YCbCr Cr:Cb format, 2x1 subsampled Cr:Cb plane"/>
++      <entry name="nv61" value="0x3136564e" summary="2 plane YCbCr Cb:Cr format, 2x1 subsampled Cb:Cr plane"/>
++      <entry name="yuv410" value="0x39565559" summary="3 plane YCbCr format, 4x4 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu410" value="0x39555659" summary="3 plane YCbCr format, 4x4 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv411" value="0x31315559" summary="3 plane YCbCr format, 4x1 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu411" value="0x31315659" summary="3 plane YCbCr format, 4x1 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv420" value="0x32315559" summary="3 plane YCbCr format, 2x2 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu420" value="0x32315659" summary="3 plane YCbCr format, 2x2 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv422" value="0x36315559" summary="3 plane YCbCr format, 2x1 subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu422" value="0x36315659" summary="3 plane YCbCr format, 2x1 subsampled Cr (1) and Cb (2) planes"/>
++      <entry name="yuv444" value="0x34325559" summary="3 plane YCbCr format, non-subsampled Cb (1) and Cr (2) planes"/>
++      <entry name="yvu444" value="0x34325659" summary="3 plane YCbCr format, non-subsampled Cr (1) and Cb (2) planes"/>
++    </enum>
++
++    <request name="create_pool">
++      <description summary="create a shm pool">
++      Create a new wl_shm_pool object.
++
++      The pool can be used to create shared memory based buffer
++      objects.  The server will mmap size bytes of the passed file
++      descriptor, to use as backing memory for the pool.
++      </description>
++      <arg name="id" type="new_id" interface="wl_shm_pool" summary="pool to create"/>
++      <arg name="fd" type="fd" summary="file descriptor for the pool"/>
++      <arg name="size" type="int" summary="pool size, in bytes"/>
++    </request>
++
++    <event name="format">
++      <description summary="pixel format description">
++      Informs the client about a valid pixel format that
++      can be used for buffers. Known formats include
++      argb8888 and xrgb8888.
++      </description>
++      <arg name="format" type="uint" enum="format" summary="buffer pixel format"/>
++    </event>
++  </interface>
++
++  <interface name="wl_buffer" version="1">
++    <description summary="content for a wl_surface">
++      A buffer provides the content for a wl_surface. Buffers are
++      created through factory interfaces such as wl_drm, wl_shm or
++      similar. It has a width and a height and can be attached to a
++      wl_surface, but the mechanism by which a client provides and
++      updates the contents is defined by the buffer factory interface.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy a buffer">
++      Destroy a buffer. If and how you need to release the backing
++      storage is defined by the buffer factory interface.
++
++      For possible side-effects to a surface, see wl_surface.attach.
++      </description>
++    </request>
++
++    <event name="release">
++      <description summary="compositor releases buffer">
++      Sent when this wl_buffer is no longer used by the compositor.
++      The client is now free to reuse or destroy this buffer and its
++      backing storage.
++
++      If a client receives a release event before the frame callback
++      requested in the same wl_surface.commit that attaches this
++      wl_buffer to a surface, then the client is immediately free to
++      reuse the buffer and its backing storage, and does not need a
++      second buffer for the next surface content update. Typically
++      this is possible, when the compositor maintains a copy of the
++      wl_surface contents, e.g. as a GL texture. This is an important
++      optimization for GL(ES) compositors with wl_shm clients.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="wl_data_offer" version="3">
++    <description summary="offer to transfer data">
++      A wl_data_offer represents a piece of data offered for transfer
++      by another client (the source client).  It is used by the
++      copy-and-paste and drag-and-drop mechanisms.  The offer
++      describes the different mime types that the data can be
++      converted to and provides the mechanism for transferring the
++      data directly from the source client.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_finish" value="0"
++           summary="finish request was called untimely"/>
++      <entry name="invalid_action_mask" value="1"
++           summary="action mask contains invalid values"/>
++      <entry name="invalid_action" value="2"
++           summary="action argument has an invalid value"/>
++      <entry name="invalid_offer" value="3"
++           summary="offer doesn't accept this request"/>
++    </enum>
++
++    <request name="accept">
++      <description summary="accept one of the offered mime types">
++      Indicate that the client can accept the given mime type, or
++      NULL for not accepted.
++
++      For objects of version 2 or older, this request is used by the
++      client to give feedback whether the client can receive the given
++      mime type, or NULL if none is accepted; the feedback does not
++      determine whether the drag-and-drop operation succeeds or not.
++
++      For objects of version 3 or newer, this request determines the
++      final result of the drag-and-drop operation. If the end result
++      is that no mime types were accepted, the drag-and-drop operation
++      will be cancelled and the corresponding drag source will receive
++      wl_data_source.cancelled. Clients may still use this event in
++      conjunction with wl_data_source.action for feedback.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the accept request"/>
++      <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the client"/>
++    </request>
++
++    <request name="receive">
++      <description summary="request that the data is transferred">
++      To transfer the offered data, the client issues this request
++      and indicates the mime type it wants to receive.  The transfer
++      happens through the passed file descriptor (typically created
++      with the pipe system call).  The source client writes the data
++      in the mime type representation requested and then closes the
++      file descriptor.
++
++      The receiving client reads from the read end of the pipe until
++      EOF and then closes its end, at which point the transfer is
++      complete.
++
++      This request may happen multiple times for different mime types,
++      both before and after wl_data_device.drop. Drag-and-drop destination
++      clients may preemptively fetch data or examine it more closely to
++      determine acceptance.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type desired by receiver"/>
++      <arg name="fd" type="fd" summary="file descriptor for data transfer"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy data offer">
++      Destroy the data offer.
++      </description>
++    </request>
++
++    <event name="offer">
++      <description summary="advertise offered mime type">
++      Sent immediately after creating the wl_data_offer object.  One
++      event per offered mime type.
++      </description>
++      <arg name="mime_type" type="string" summary="offered mime type"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="finish" since="3">
++      <description summary="the offer will no longer be used">
++      Notifies the compositor that the drag destination successfully
++      finished the drag-and-drop operation.
++
++      Upon receiving this request, the compositor will emit
++      wl_data_source.dnd_finished on the drag source client.
++
++      It is a client error to perform other requests than
++      wl_data_offer.destroy after this one. It is also an error to perform
++      this request after a NULL mime type has been set in
++      wl_data_offer.accept or no action was received through
++      wl_data_offer.action.
++      </description>
++    </request>
++
++    <request name="set_actions" since="3">
++      <description summary="set the available/preferred drag-and-drop actions">
++      Sets the actions that the destination side client supports for
++      this operation. This request may trigger the emission of
++      wl_data_source.action and wl_data_offer.action events if the compositor
++      needs to change the selected action.
++
++      This request can be called multiple times throughout the
++      drag-and-drop operation, typically in response to wl_data_device.enter
++      or wl_data_device.motion events.
++
++      This request determines the final result of the drag-and-drop
++      operation. If the end result is that no action is accepted,
++      the drag source will receive wl_drag_source.cancelled.
++
++      The dnd_actions argument must contain only values expressed in the
++      wl_data_device_manager.dnd_actions enum, and the preferred_action
++      argument must only contain one of those values set, otherwise it
++      will result in a protocol error.
++
++      While managing an "ask" action, the destination drag-and-drop client
++      may perform further wl_data_offer.receive requests, and is expected
++      to perform one last wl_data_offer.set_actions request with a preferred
++      action other than "ask" (and optionally wl_data_offer.accept) before
++      requesting wl_data_offer.finish, in order to convey the action selected
++      by the user. If the preferred action is not in the
++      wl_data_offer.source_actions mask, an error will be raised.
++
++      If the "ask" action is dismissed (e.g. user cancellation), the client
++      is expected to perform wl_data_offer.destroy right away.
++
++      This request can only be made on drag-and-drop offers, a protocol error
++      will be raised otherwise.
++      </description>
++      <arg name="dnd_actions" type="uint" summary="actions supported by the destination client"/>
++      <arg name="preferred_action" type="uint" summary="action preferred by the destination client"/>
++    </request>
++
++    <event name="source_actions" since="3">
++      <description summary="notify the source-side available actions">
++      This event indicates the actions offered by the data source. It
++      will be sent right after wl_data_device.enter, or anytime the source
++      side changes its offered actions through wl_data_source.set_actions.
++      </description>
++      <arg name="source_actions" type="uint" summary="actions offered by the data source"/>
++    </event>
++
++    <event name="action" since="3">
++      <description summary="notify the selected action">
++      This event indicates the action selected by the compositor after
++      matching the source/destination side actions. Only one action (or
++      none) will be offered here.
++
++      This event can be emitted multiple times during the drag-and-drop
++      operation in response to destination side action changes through
++      wl_data_offer.set_actions.
++
++      This event will no longer be emitted after wl_data_device.drop
++      happened on the drag-and-drop destination, the client must
++      honor the last action received, or the last preferred one set
++      through wl_data_offer.set_actions when handling an "ask" action.
++
++      Compositors may also change the selected action on the fly, mainly
++      in response to keyboard modifier changes during the drag-and-drop
++      operation.
++
++      The most recent action received is always the valid one. Prior to
++      receiving wl_data_device.drop, the chosen action may change (e.g.
++      due to keyboard modifiers being pressed). At the time of receiving
++      wl_data_device.drop the drag-and-drop destination must honor the
++      last action received.
++
++      Action changes may still happen after wl_data_device.drop,
++      especially on "ask" actions, where the drag-and-drop destination
++      may choose another action afterwards. Action changes happening
++      at this stage are always the result of inter-client negotiation, the
++      compositor shall no longer be able to induce a different action.
++
++      Upon "ask" actions, it is expected that the drag-and-drop destination
++      may potentially choose a different action and/or mime type,
++      based on wl_data_offer.source_actions and finally chosen by the
++      user (e.g. popping up a menu with the available options). The
++      final wl_data_offer.set_actions and wl_data_offer.accept requests
++      must happen before the call to wl_data_offer.finish.
++      </description>
++      <arg name="dnd_action" type="uint" summary="action selected by the compositor"/>
++    </event>
++  </interface>
++
++  <interface name="wl_data_source" version="3">
++    <description summary="offer to transfer data">
++      The wl_data_source object is the source side of a wl_data_offer.
++      It is created by the source client in a data transfer and
++      provides a way to describe the offered data and a way to respond
++      to requests to transfer the data.
++    </description>
++
++    <enum name="error">
++      <entry name="invalid_action_mask" value="0"
++           summary="action mask contains invalid values"/>
++      <entry name="invalid_source" value="1"
++           summary="source doesn't accept this request"/>
++    </enum>
++
++    <request name="offer">
++      <description summary="add an offered mime type">
++      This request adds a mime type to the set of mime types
++      advertised to targets.  Can be called several times to offer
++      multiple types.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type offered by the data source"/>
++    </request>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy the data source">
++      Destroy the data source.
++      </description>
++    </request>
++
++    <event name="target">
++      <description summary="a target accepts an offered mime type">
++      Sent when a target accepts pointer_focus or motion events.  If
++      a target does not accept any of the offered types, type is NULL.
++
++      Used for feedback during drag-and-drop.
++      </description>
++      <arg name="mime_type" type="string" allow-null="true" summary="mime type accepted by the target"/>
++    </event>
++
++    <event name="send">
++      <description summary="send the data">
++      Request for data from the client.  Send the data as the
++      specified mime type over the passed file descriptor, then
++      close it.
++      </description>
++      <arg name="mime_type" type="string" summary="mime type for the data"/>
++      <arg name="fd" type="fd" summary="file descriptor for the data"/>
++    </event>
++
++    <event name="cancelled">
++      <description summary="selection was cancelled">
++      This data source is no longer valid. There are several reasons why
++      this could happen:
++
++      - The data source has been replaced by another data source.
++      - The drag-and-drop operation was performed, but the drop destination
++        did not accept any of the mime types offered through
++        wl_data_source.target.
++      - The drag-and-drop operation was performed, but the drop destination
++        did not select any of the actions present in the mask offered through
++        wl_data_source.action.
++      - The drag-and-drop operation was performed but didn't happen over a
++        surface.
++      - The compositor cancelled the drag-and-drop operation (e.g. compositor
++        dependent timeouts to avoid stale drag-and-drop transfers).
++
++      The client should clean up and destroy this data source.
++
++      For objects of version 2 or older, wl_data_source.cancelled will
++      only be emitted if the data source was replaced by another data
++      source.
++      </description>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="set_actions" since="3">
++      <description summary="set the available drag-and-drop actions">
++      Sets the actions that the source side client supports for this
++      operation. This request may trigger wl_data_source.action and
++      wl_data_offer.action events if the compositor needs to change the
++      selected action.
++
++      The dnd_actions argument must contain only values expressed in the
++      wl_data_device_manager.dnd_actions enum, otherwise it will result
++      in a protocol error.
++
++      This request must be made once only, and can only be made on sources
++      used in drag-and-drop, so it must be performed before
++      wl_data_device.start_drag. Attempting to use the source other than
++      for drag-and-drop will raise a protocol error.
++      </description>
++      <arg name="dnd_actions" type="uint" summary="actions supported by the data source"/>
++    </request>
++
++    <event name="dnd_drop_performed" since="3">
++      <description summary="the drag-and-drop operation physically finished">
++      The user performed the drop action. This event does not indicate
++      acceptance, wl_data_source.cancelled may still be emitted afterwards
++      if the drop destination does not accept any mime type.
++
++      However, this event might however not be received if the compositor
++      cancelled the drag-and-drop operation before this event could happen.
++
++      Note that the data_source may still be used in the future and should
++      not be destroyed here.
++      </description>
++    </event>
++
++    <event name="dnd_finished" since="3">
++      <description summary="the drag-and-drop operation concluded">
++      The drop destination finished interoperating with this data
++      source, so the client is now free to destroy this data source and
++      free all associated data.
++
++      If the action used to perform the operation was "move", the
++      source can now delete the transferred data.
++      </description>
++    </event>
++
++    <event name="action" since="3">
++      <description summary="notify the selected action">
++      This event indicates the action selected by the compositor after
++      matching the source/destination side actions. Only one action (or
++      none) will be offered here.
++
++      This event can be emitted multiple times during the drag-and-drop
++      operation, mainly in response to destination side changes through
++      wl_data_offer.set_actions, and as the data device enters/leaves
++      surfaces.
++
++      It is only possible to receive this event after
++      wl_data_source.dnd_drop_performed if the drag-and-drop operation
++      ended in an "ask" action, in which case the final wl_data_source.action
++      event will happen immediately before wl_data_source.dnd_finished.
++
++      Compositors may also change the selected action on the fly, mainly
++      in response to keyboard modifier changes during the drag-and-drop
++      operation.
++
++      The most recent action received is always the valid one. The chosen
++      action may change alongside negotiation (e.g. an "ask" action can turn
++      into a "move" operation), so the effects of the final action must
++      always be applied in wl_data_offer.dnd_finished.
++
++      Clients can trigger cursor surface changes from this point, so
++      they reflect the current action.
++      </description>
++      <arg name="dnd_action" type="uint" summary="action selected by the compositor"/>
++    </event>
++  </interface>
++
++  <interface name="wl_data_device" version="3">
++    <description summary="data transfer device">
++      There is one wl_data_device per seat which can be obtained
++      from the global wl_data_device_manager singleton.
++
++      A wl_data_device provides access to inter-client data transfer
++      mechanisms such as copy-and-paste and drag-and-drop.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="start_drag">
++      <description summary="start drag-and-drop operation">
++      This request asks the compositor to start a drag-and-drop
++      operation on behalf of the client.
++
++      The source argument is the data source that provides the data
++      for the eventual data transfer. If source is NULL, enter, leave
++      and motion events are sent only to the client that initiated the
++      drag and the client is expected to handle the data passing
++      internally.
++
++      The origin surface is the surface where the drag originates and
++      the client must have an active implicit grab that matches the
++      serial.
++
++      The icon surface is an optional (can be NULL) surface that
++      provides an icon to be moved around with the cursor.  Initially,
++      the top-left corner of the icon surface is placed at the cursor
++      hotspot, but subsequent wl_surface.attach request can move the
++      relative position. Attach requests must be confirmed with
++      wl_surface.commit as usual. The icon surface is given the role of
++      a drag-and-drop icon. If the icon surface already has another role,
++      it raises a protocol error.
++
++      The current and pending input regions of the icon wl_surface are
++      cleared, and wl_surface.set_input_region is ignored until the
++      wl_surface is no longer used as the icon surface. When the use
++      as an icon ends, the current and pending input regions become
++      undefined, and the wl_surface is unmapped.
++      </description>
++      <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the eventual transfer"/>
++      <arg name="origin" type="object" interface="wl_surface" summary="surface where the drag originates"/>
++      <arg name="icon" type="object" interface="wl_surface" allow-null="true" summary="drag-and-drop icon surface"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the origin"/>
++    </request>
++
++    <request name="set_selection">
++      <description summary="copy data to the selection">
++      This request asks the compositor to set the selection
++      to the data from the source on behalf of the client.
++
++      To unset the selection, set the source to NULL.
++      </description>
++      <arg name="source" type="object" interface="wl_data_source" allow-null="true" summary="data source for the selection"/>
++      <arg name="serial" type="uint" summary="serial number of the event that triggered this request"/>
++    </request>
++
++    <event name="data_offer">
++      <description summary="introduce a new wl_data_offer">
++      The data_offer event introduces a new wl_data_offer object,
++      which will subsequently be used in either the
++      data_device.enter event (for drag-and-drop) or the
++      data_device.selection event (for selections).  Immediately
++      following the data_device.data_offer event, the new data_offer
++      object will send out data_offer.offer events to describe the
++      mime types it offers.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_offer" summary="the new data_offer object"/>
++    </event>
++
++    <event name="enter">
++      <description summary="initiate drag-and-drop session">
++      This event is sent when an active drag-and-drop pointer enters
++      a surface owned by the client.  The position of the pointer at
++      enter time is provided by the x and y arguments, in surface-local
++      coordinates.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="client surface entered"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++      <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++         summary="source data_offer object"/>
++    </event>
++
++    <event name="leave">
++      <description summary="end drag-and-drop session">
++      This event is sent when the drag-and-drop pointer leaves the
++      surface and the session ends.  The client must destroy the
++      wl_data_offer introduced at enter time at this point.
++      </description>
++    </event>
++
++    <event name="motion">
++      <description summary="drag-and-drop session motion">
++      This event is sent when the drag-and-drop pointer moves within
++      the currently focused surface. The new position of the pointer
++      is provided by the x and y arguments, in surface-local
++      coordinates.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="drop">
++      <description summary="end drag-and-drop session successfully">
++      The event is sent when a drag-and-drop operation is ended
++      because the implicit grab is removed.
++
++      The drag-and-drop destination is expected to honor the last action
++      received through wl_data_offer.action, if the resulting action is
++      "copy" or "move", the destination can still perform
++      wl_data_offer.receive requests, and is expected to end all
++      transfers with a wl_data_offer.finish request.
++
++      If the resulting action is "ask", the action will not be considered
++      final. The drag-and-drop destination is expected to perform one last
++      wl_data_offer.set_actions request, or wl_data_offer.destroy in order
++      to cancel the operation.
++      </description>
++    </event>
++
++    <event name="selection">
++      <description summary="advertise new selection">
++      The selection event is sent out to notify the client of a new
++      wl_data_offer for the selection for this device.  The
++      data_device.data_offer and the data_offer.offer events are
++      sent out immediately before this event to introduce the data
++      offer object.  The selection event is sent to a client
++      immediately before receiving keyboard focus and when a new
++      selection is set while the client has keyboard focus.  The
++      data_offer is valid until a new data_offer or NULL is received
++      or until the client loses keyboard focus.  The client must
++      destroy the previous selection data_offer, if any, upon receiving
++      this event.
++      </description>
++      <arg name="id" type="object" interface="wl_data_offer" allow-null="true"
++         summary="selection data_offer object"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <request name="release" type="destructor" since="2">
++      <description summary="destroy data device">
++      This request destroys the data device.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="wl_data_device_manager" version="3">
++    <description summary="data transfer interface">
++      The wl_data_device_manager is a singleton global object that
++      provides access to inter-client data transfer mechanisms such as
++      copy-and-paste and drag-and-drop.  These mechanisms are tied to
++      a wl_seat and this interface lets a client get a wl_data_device
++      corresponding to a wl_seat.
++
++      Depending on the version bound, the objects created from the bound
++      wl_data_device_manager object will have different requirements for
++      functioning properly. See wl_data_source.set_actions,
++      wl_data_offer.accept and wl_data_offer.finish for details.
++    </description>
++
++    <request name="create_data_source">
++      <description summary="create a new data source">
++      Create a new data source.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_source" summary="data source to create"/>
++    </request>
++
++    <request name="get_data_device">
++      <description summary="create a new data device">
++      Create a new data device for a given seat.
++      </description>
++      <arg name="id" type="new_id" interface="wl_data_device" summary="data device to create"/>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat associated with the data device"/>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <enum name="dnd_action" bitfield="true" since="3">
++      <description summary="drag and drop actions">
++      This is a bitmask of the available/preferred actions in a
++      drag-and-drop operation.
++
++      In the compositor, the selected action is a result of matching the
++      actions offered by the source and destination sides.  "action" events
++      with a "none" action will be sent to both source and destination if
++      there is no match. All further checks will effectively happen on
++      (source actions ∩ destination actions).
++
++      In addition, compositors may also pick different actions in
++      reaction to key modifiers being pressed. One common design that
++      is used in major toolkits (and the behavior recommended for
++      compositors) is:
++
++      - If no modifiers are pressed, the first match (in bit order)
++        will be used.
++      - Pressing Shift selects "move", if enabled in the mask.
++      - Pressing Control selects "copy", if enabled in the mask.
++
++      Behavior beyond that is considered implementation-dependent.
++      Compositors may for example bind other modifiers (like Alt/Meta)
++      or drags initiated with other buttons than BTN_LEFT to specific
++      actions (e.g. "ask").
++      </description>
++      <entry name="none" value="0" summary="no action"/>
++      <entry name="copy" value="1" summary="copy action"/>
++      <entry name="move" value="2" summary="move action"/>
++      <entry name="ask" value="4" summary="ask action"/>
++    </enum>
++  </interface>
++
++  <interface name="wl_shell" version="1">
++    <description summary="create desktop-style surfaces">
++      This interface is implemented by servers that provide
++      desktop-style user interfaces.
++
++      It allows clients to associate a wl_shell_surface with
++      a basic surface.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="get_shell_surface">
++      <description summary="create a shell surface from a surface">
++      Create a shell surface for an existing surface. This gives
++      the wl_surface the role of a shell surface. If the wl_surface
++      already has another role, it raises a protocol error.
++
++      Only one shell surface can be associated with a given surface.
++      </description>
++      <arg name="id" type="new_id" interface="wl_shell_surface" summary="shell surface to create"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface to be given the shell surface role"/>
++    </request>
++  </interface>
++
++  <interface name="wl_shell_surface" version="1">
++    <description summary="desktop-style metadata interface">
++      An interface that may be implemented by a wl_surface, for
++      implementations that provide a desktop-style user interface.
++
++      It provides requests to treat surfaces like toplevel, fullscreen
++      or popup windows, move, resize or maximize them, associate
++      metadata like title and class, etc.
++
++      On the server side the object is automatically destroyed when
++      the related wl_surface is destroyed. On the client side,
++      wl_shell_surface_destroy() must be called before destroying
++      the wl_surface object.
++    </description>
++
++    <request name="pong">
++      <description summary="respond to a ping event">
++      A client must respond to a ping event with a pong request or
++      the client may be deemed unresponsive.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the ping event"/>
++    </request>
++
++    <request name="move">
++      <description summary="start an interactive move">
++      Start a pointer-driven move of the surface.
++
++      This request must be used in response to a button press event.
++      The server may ignore move requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++    </request>
++
++    <enum name="resize" bitfield="true">
++      <description summary="edge values for resizing">
++      These values are used to indicate which edge of a surface
++      is being dragged in a resize operation. The server may
++      use this information to adapt its behavior, e.g. choose
++      an appropriate cursor image.
++      </description>
++      <entry name="none" value="0" summary="no edge"/>
++      <entry name="top" value="1" summary="top edge"/>
++      <entry name="bottom" value="2" summary="bottom edge"/>
++      <entry name="left" value="4" summary="left edge"/>
++      <entry name="top_left" value="5" summary="top and left edges"/>
++      <entry name="bottom_left" value="6" summary="bottom and left edges"/>
++      <entry name="right" value="8" summary="right edge"/>
++      <entry name="top_right" value="9" summary="top and right edges"/>
++      <entry name="bottom_right" value="10" summary="bottom and right edges"/>
++    </enum>
++
++    <request name="resize">
++      <description summary="start an interactive resize">
++      Start a pointer-driven resizing of the surface.
++
++      This request must be used in response to a button press event.
++      The server may ignore resize requests depending on the state of
++      the surface (e.g. fullscreen or maximized).
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++      <arg name="edges" type="uint" enum="resize" summary="which edge or corner is being dragged"/>
++    </request>
++
++    <request name="set_toplevel">
++      <description summary="make the surface a toplevel surface">
++      Map the surface as a toplevel surface.
++
++      A toplevel surface is not fullscreen, maximized or transient.
++      </description>
++    </request>
++
++    <enum name="transient" bitfield="true">
++      <description summary="details of transient behaviour">
++      These flags specify details of the expected behaviour
++      of transient surfaces. Used in the set_transient request.
++      </description>
++      <entry name="inactive" value="0x1" summary="do not set keyboard focus"/>
++    </enum>
++
++    <request name="set_transient">
++      <description summary="make the surface a transient surface">
++      Map the surface relative to an existing surface.
++
++      The x and y arguments specify the location of the upper left
++      corner of the surface relative to the upper left corner of the
++      parent surface, in surface-local coordinates.
++
++      The flags argument controls details of the transient behaviour.
++      </description>
++      <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++    </request>
++
++    <enum name="fullscreen_method">
++      <description summary="different method to set the surface fullscreen">
++      Hints to indicate to the compositor how to deal with a conflict
++      between the dimensions of the surface and the dimensions of the
++      output. The compositor is free to ignore this parameter.
++      </description>
++      <entry name="default" value="0" summary="no preference, apply default policy"/>
++      <entry name="scale" value="1" summary="scale, preserve the surface's aspect ratio and center on output"/>
++      <entry name="driver" value="2" summary="switch output mode to the smallest mode that can fit the surface, add black borders to compensate size mismatch"/>
++      <entry name="fill" value="3" summary="no upscaling, center on output and add black borders to compensate size mismatch"/>
++    </enum>
++
++    <request name="set_fullscreen">
++      <description summary="make the surface a fullscreen surface">
++      Map the surface as a fullscreen surface.
++
++      If an output parameter is given then the surface will be made
++      fullscreen on that output. If the client does not specify the
++      output then the compositor will apply its policy - usually
++      choosing the output on which the surface has the biggest surface
++      area.
++
++      The client may specify a method to resolve a size conflict
++      between the output size and the surface size - this is provided
++      through the method parameter.
++
++      The framerate parameter is used only when the method is set
++      to "driver", to indicate the preferred framerate. A value of 0
++      indicates that the client does not care about framerate.  The
++      framerate is specified in mHz, that is framerate of 60000 is 60Hz.
++
++      A method of "scale" or "driver" implies a scaling operation of
++      the surface, either via a direct scaling operation or a change of
++      the output mode. This will override any kind of output scaling, so
++      that mapping a surface with a buffer size equal to the mode can
++      fill the screen independent of buffer_scale.
++
++      A method of "fill" means we don't scale up the buffer, however
++      any output scale is applied. This means that you may run into
++      an edge case where the application maps a buffer with the same
++      size of the output mode but buffer_scale 1 (thus making a
++      surface larger than the output). In this case it is allowed to
++      downscale the results to fit the screen.
++
++      The compositor must reply to this request with a configure event
++      with the dimensions for the output on which the surface will
++      be made fullscreen.
++      </description>
++      <arg name="method" type="uint" enum="fullscreen_method" summary="method for resolving size conflict"/>
++      <arg name="framerate" type="uint" summary="framerate in mHz"/>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"
++         summary="output on which the surface is to be fullscreen"/>
++    </request>
++
++    <request name="set_popup">
++      <description summary="make the surface a popup surface">
++      Map the surface as a popup.
++
++      A popup surface is a transient surface with an added pointer
++      grab.
++
++      An existing implicit grab will be changed to owner-events mode,
++      and the popup grab will continue after the implicit grab ends
++      (i.e. releasing the mouse button does not cause the popup to
++      be unmapped).
++
++      The popup grab continues until the window is destroyed or a
++      mouse button is pressed in any other client's window. A click
++      in any of the client's surfaces is reported as normal, however,
++      clicks in other clients' surfaces will be discarded and trigger
++      the callback.
++
++      The x and y arguments specify the location of the upper left
++      corner of the surface relative to the upper left corner of the
++      parent surface, in surface-local coordinates.
++      </description>
++      <arg name="seat" type="object" interface="wl_seat" summary="seat whose pointer is used"/>
++      <arg name="serial" type="uint" summary="serial number of the implicit grab on the pointer"/>
++      <arg name="parent" type="object" interface="wl_surface" summary="parent surface"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="flags" type="uint" enum="transient" summary="transient surface behavior"/>
++    </request>
++
++    <request name="set_maximized">
++      <description summary="make the surface a maximized surface">
++      Map the surface as a maximized surface.
++
++      If an output parameter is given then the surface will be
++      maximized on that output. If the client does not specify the
++      output then the compositor will apply its policy - usually
++      choosing the output on which the surface has the biggest surface
++      area.
++
++      The compositor will reply with a configure event telling
++      the expected new surface size. The operation is completed
++      on the next buffer attach to this surface.
++
++      A maximized surface typically fills the entire output it is
++      bound to, except for desktop elements such as panels. This is
++      the main difference between a maximized shell surface and a
++      fullscreen shell surface.
++
++      The details depend on the compositor implementation.
++      </description>
++      <arg name="output" type="object" interface="wl_output" allow-null="true"
++         summary="output on which the surface is to be maximized"/>
++    </request>
++
++    <request name="set_title">
++      <description summary="set surface title">
++      Set a short title for the surface.
++
++      This string may be used to identify the surface in a task bar,
++      window list, or other user interface elements provided by the
++      compositor.
++
++      The string must be encoded in UTF-8.
++      </description>
++      <arg name="title" type="string" summary="surface title"/>
++    </request>
++
++    <request name="set_class">
++      <description summary="set surface class">
++      Set a class for the surface.
++
++      The surface class identifies the general class of applications
++      to which the surface belongs. A common convention is to use the
++      file name (or the full path if it is a non-standard location) of
++      the application's .desktop file as the class.
++      </description>
++      <arg name="class_" type="string" summary="surface class"/>
++    </request>
++
++    <event name="ping">
++      <description summary="ping client">
++      Ping a client to check if it is receiving events and sending
++      requests. A client is expected to reply with a pong request.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the ping"/>
++    </event>
++
++    <event name="configure">
++      <description summary="suggest resize">
++      The configure event asks the client to resize its surface.
++
++      The size is a hint, in the sense that the client is free to
++      ignore it if it doesn't resize, pick a smaller size (to
++      satisfy aspect ratio or resize in steps of NxM pixels).
++
++      The edges parameter provides a hint about how the surface
++      was resized. The client may use this information to decide
++      how to adjust its content to the new size (e.g. a scrolling
++      area might adjust its content position to leave the viewable
++      content unmoved).
++
++      The client is free to dismiss all but the last configure
++      event it received.
++
++      The width and height arguments specify the size of the window
++      in surface-local coordinates.
++      </description>
++      <arg name="edges" type="uint" enum="resize" summary="how the surface was resized"/>
++      <arg name="width" type="int" summary="new width of the surface"/>
++      <arg name="height" type="int" summary="new height of the surface"/>
++    </event>
++
++    <event name="popup_done">
++      <description summary="popup interaction is done">
++      The popup_done event is sent out when a popup grab is broken,
++      that is, when the user clicks a surface that doesn't belong
++      to the client owning the popup surface.
++      </description>
++    </event>
++  </interface>
++
++  <interface name="wl_surface" version="4">
++    <description summary="an onscreen surface">
++      A surface is a rectangular area that is displayed on the screen.
++      It has a location, size and pixel contents.
++
++      The size of a surface (and relative positions on it) is described
++      in surface-local coordinates, which may differ from the buffer
++      coordinates of the pixel content, in case a buffer_transform
++      or a buffer_scale is used.
++
++      A surface without a "role" is fairly useless: a compositor does
++      not know where, when or how to present it. The role is the
++      purpose of a wl_surface. Examples of roles are a cursor for a
++      pointer (as set by wl_pointer.set_cursor), a drag icon
++      (wl_data_device.start_drag), a sub-surface
++      (wl_subcompositor.get_subsurface), and a window as defined by a
++      shell protocol (e.g. wl_shell.get_shell_surface).
++
++      A surface can have only one role at a time. Initially a
++      wl_surface does not have a role. Once a wl_surface is given a
++      role, it is set permanently for the whole lifetime of the
++      wl_surface object. Giving the current role again is allowed,
++      unless explicitly forbidden by the relevant interface
++      specification.
++
++      Surface roles are given by requests in other interfaces such as
++      wl_pointer.set_cursor. The request should explicitly mention
++      that this request gives a role to a wl_surface. Often, this
++      request also creates a new protocol object that represents the
++      role and adds additional functionality to wl_surface. When a
++      client wants to destroy a wl_surface, they must destroy this 'role
++      object' before the wl_surface.
++
++      Destroying the role object does not remove the role from the
++      wl_surface, but it may stop the wl_surface from "playing the role".
++      For instance, if a wl_subsurface object is destroyed, the wl_surface
++      it was created for will be unmapped and forget its position and
++      z-order. It is allowed to create a wl_subsurface for the same
++      wl_surface again, but it is not allowed to use the wl_surface as
++      a cursor (cursor is a different role than sub-surface, and role
++      switching is not allowed).
++    </description>
++
++    <enum name="error">
++      <description summary="wl_surface error values">
++      These errors can be emitted in response to wl_surface requests.
++      </description>
++      <entry name="invalid_scale" value="0" summary="buffer scale value is invalid"/>
++      <entry name="invalid_transform" value="1" summary="buffer transform value is invalid"/>
++    </enum>
++
++    <request name="destroy" type="destructor">
++      <description summary="delete surface">
++      Deletes the surface and invalidates its object ID.
++      </description>
++    </request>
++
++    <request name="attach">
++      <description summary="set the surface contents">
++      Set a buffer as the content of this surface.
++
++      The new size of the surface is calculated based on the buffer
++      size transformed by the inverse buffer_transform and the
++      inverse buffer_scale. This means that the supplied buffer
++      must be an integer multiple of the buffer_scale.
++
++      The x and y arguments specify the location of the new pending
++      buffer's upper left corner, relative to the current buffer's upper
++      left corner, in surface-local coordinates. In other words, the
++      x and y, combined with the new surface size define in which
++      directions the surface's size changes.
++
++      Surface contents are double-buffered state, see wl_surface.commit.
++
++      The initial surface contents are void; there is no content.
++      wl_surface.attach assigns the given wl_buffer as the pending
++      wl_buffer. wl_surface.commit makes the pending wl_buffer the new
++      surface contents, and the size of the surface becomes the size
++      calculated from the wl_buffer, as described above. After commit,
++      there is no pending buffer until the next attach.
++
++      Committing a pending wl_buffer allows the compositor to read the
++      pixels in the wl_buffer. The compositor may access the pixels at
++      any time after the wl_surface.commit request. When the compositor
++      will not access the pixels anymore, it will send the
++      wl_buffer.release event. Only after receiving wl_buffer.release,
++      the client may reuse the wl_buffer. A wl_buffer that has been
++      attached and then replaced by another attach instead of committed
++      will not receive a release event, and is not used by the
++      compositor.
++
++      Destroying the wl_buffer after wl_buffer.release does not change
++      the surface contents. However, if the client destroys the
++      wl_buffer before receiving the wl_buffer.release event, the surface
++      contents become undefined immediately.
++
++      If wl_surface.attach is sent with a NULL wl_buffer, the
++      following wl_surface.commit will remove the surface content.
++      </description>
++      <arg name="buffer" type="object" interface="wl_buffer" allow-null="true"
++         summary="buffer of surface contents"/>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <request name="damage">
++      <description summary="mark part of the surface damaged">
++      This request is used to describe the regions where the pending
++      buffer is different from the current surface contents, and where
++      the surface therefore needs to be repainted. The compositor
++      ignores the parts of the damage that fall outside of the surface.
++
++      Damage is double-buffered state, see wl_surface.commit.
++
++      The damage rectangle is specified in surface-local coordinates,
++      where x and y specify the upper left corner of the damage rectangle.
++
++      The initial value for pending damage is empty: no damage.
++      wl_surface.damage adds pending damage: the new pending damage
++      is the union of old pending damage and the given rectangle.
++
++      wl_surface.commit assigns pending damage as the current damage,
++      and clears pending damage. The server will clear the current
++      damage as it repaints the surface.
++
++      Alternatively, damage can be posted with wl_surface.damage_buffer
++      which uses buffer coordinates instead of surface coordinates,
++      and is probably the preferred and intuitive way of doing this.
++      </description>
++      <arg name="x" type="int" summary="surface-local x coordinate"/>
++      <arg name="y" type="int" summary="surface-local y coordinate"/>
++      <arg name="width" type="int" summary="width of damage rectangle"/>
++      <arg name="height" type="int" summary="height of damage rectangle"/>
++    </request>
++
++    <request name="frame">
++      <description summary="request a frame throttling hint">
++      Request a notification when it is a good time to start drawing a new
++      frame, by creating a frame callback. This is useful for throttling
++      redrawing operations, and driving animations.
++
++      When a client is animating on a wl_surface, it can use the 'frame'
++      request to get notified when it is a good time to draw and commit the
++      next frame of animation. If the client commits an update earlier than
++      that, it is likely that some updates will not make it to the display,
++      and the client is wasting resources by drawing too often.
++
++      The frame request will take effect on the next wl_surface.commit.
++      The notification will only be posted for one frame unless
++      requested again. For a wl_surface, the notifications are posted in
++      the order the frame requests were committed.
++
++      The server must send the notifications so that a client
++      will not send excessive updates, while still allowing
++      the highest possible update rate for clients that wait for the reply
++      before drawing again. The server should give some time for the client
++      to draw and commit after sending the frame callback events to let it
++      hit the next output refresh.
++
++      A server should avoid signaling the frame callbacks if the
++      surface is not visible in any way, e.g. the surface is off-screen,
++      or completely obscured by other opaque surfaces.
++
++      The object returned by this request will be destroyed by the
++      compositor after the callback is fired and as such the client must not
++      attempt to use it after that point.
++
++      The callback_data passed in the callback is the current time, in
++      milliseconds, with an undefined base.
++      </description>
++      <arg name="callback" type="new_id" interface="wl_callback" summary="callback object for the frame request"/>
++    </request>
++
++    <request name="set_opaque_region">
++      <description summary="set opaque region">
++      This request sets the region of the surface that contains
++      opaque content.
++
++      The opaque region is an optimization hint for the compositor
++      that lets it optimize the redrawing of content behind opaque
++      regions.  Setting an opaque region is not required for correct
++      behaviour, but marking transparent content as opaque will result
++      in repaint artifacts.
++
++      The opaque region is specified in surface-local coordinates.
++
++      The compositor ignores the parts of the opaque region that fall
++      outside of the surface.
++
++      Opaque region is double-buffered state, see wl_surface.commit.
++
++      wl_surface.set_opaque_region changes the pending opaque region.
++      wl_surface.commit copies the pending region to the current region.
++      Otherwise, the pending and current regions are never changed.
++
++      The initial value for an opaque region is empty. Setting the pending
++      opaque region has copy semantics, and the wl_region object can be
++      destroyed immediately. A NULL wl_region causes the pending opaque
++      region to be set to empty.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="opaque region of the surface"/>
++    </request>
++
++    <request name="set_input_region">
++      <description summary="set input region">
++      This request sets the region of the surface that can receive
++      pointer and touch events.
++
++      Input events happening outside of this region will try the next
++      surface in the server surface stack. The compositor ignores the
++      parts of the input region that fall outside of the surface.
++
++      The input region is specified in surface-local coordinates.
++
++      Input region is double-buffered state, see wl_surface.commit.
++
++      wl_surface.set_input_region changes the pending input region.
++      wl_surface.commit copies the pending region to the current region.
++      Otherwise the pending and current regions are never changed,
++      except cursor and icon surfaces are special cases, see
++      wl_pointer.set_cursor and wl_data_device.start_drag.
++
++      The initial value for an input region is infinite. That means the
++      whole surface will accept input. Setting the pending input region
++      has copy semantics, and the wl_region object can be destroyed
++      immediately. A NULL wl_region causes the input region to be set
++      to infinite.
++      </description>
++      <arg name="region" type="object" interface="wl_region" allow-null="true"
++         summary="input region of the surface"/>
++    </request>
++
++    <request name="commit">
++      <description summary="commit pending surface state">
++      Surface state (input, opaque, and damage regions, attached buffers,
++      etc.) is double-buffered. Protocol requests modify the pending state,
++      as opposed to the current state in use by the compositor. A commit
++      request atomically applies all pending state, replacing the current
++      state. After commit, the new pending state is as documented for each
++      related request.
++
++      On commit, a pending wl_buffer is applied first, and all other state
++      second. This means that all coordinates in double-buffered state are
++      relative to the new wl_buffer coming into use, except for
++      wl_surface.attach itself. If there is no pending wl_buffer, the
++      coordinates are relative to the current surface contents.
++
++      All requests that need a commit to become effective are documented
++      to affect double-buffered state.
++
++      Other interfaces may add further double-buffered surface state.
++      </description>
++    </request>
++
++    <event name="enter">
++      <description summary="surface enters an output">
++      This is emitted whenever a surface's creation, movement, or resizing
++      results in some part of it being within the scanout region of an
++      output.
++
++      Note that a surface may be overlapping with zero or more outputs.
++      </description>
++      <arg name="output" type="object" interface="wl_output" summary="output entered by the surface"/>
++    </event>
++
++    <event name="leave">
++      <description summary="surface leaves an output">
++      This is emitted whenever a surface's creation, movement, or resizing
++      results in it no longer having any part of it within the scanout region
++      of an output.
++      </description>
++      <arg name="output" type="object" interface="wl_output" summary="output left by the surface"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <request name="set_buffer_transform" since="2">
++      <description summary="sets the buffer transformation">
++      This request sets an optional transformation on how the compositor
++      interprets the contents of the buffer attached to the surface. The
++      accepted values for the transform parameter are the values for
++      wl_output.transform.
++
++      Buffer transform is double-buffered state, see wl_surface.commit.
++
++      A newly created surface has its buffer transformation set to normal.
++
++      wl_surface.set_buffer_transform changes the pending buffer
++      transformation. wl_surface.commit copies the pending buffer
++      transformation to the current one. Otherwise, the pending and current
++      values are never changed.
++
++      The purpose of this request is to allow clients to render content
++      according to the output transform, thus permitting the compositor to
++      use certain optimizations even if the display is rotated. Using
++      hardware overlays and scanning out a client buffer for fullscreen
++      surfaces are examples of such optimizations. Those optimizations are
++      highly dependent on the compositor implementation, so the use of this
++      request should be considered on a case-by-case basis.
++
++      Note that if the transform value includes 90 or 270 degree rotation,
++      the width of the buffer will become the surface height and the height
++      of the buffer will become the surface width.
++
++      If transform is not one of the values from the
++      wl_output.transform enum the invalid_transform protocol error
++      is raised.
++      </description>
++      <arg name="transform" type="int" enum="wl_output.transform"
++         summary="transform for interpreting buffer contents"/>
++    </request>
++
++    <!-- Version 3 additions -->
++
++    <request name="set_buffer_scale" since="3">
++      <description summary="sets the buffer scaling factor">
++      This request sets an optional scaling factor on how the compositor
++      interprets the contents of the buffer attached to the window.
++
++      Buffer scale is double-buffered state, see wl_surface.commit.
++
++      A newly created surface has its buffer scale set to 1.
++
++      wl_surface.set_buffer_scale changes the pending buffer scale.
++      wl_surface.commit copies the pending buffer scale to the current one.
++      Otherwise, the pending and current values are never changed.
++
++      The purpose of this request is to allow clients to supply higher
++      resolution buffer data for use on high resolution outputs. It is
++      intended that you pick the same buffer scale as the scale of the
++      output that the surface is displayed on. This means the compositor
++      can avoid scaling when rendering the surface on that output.
++
++      Note that if the scale is larger than 1, then you have to attach
++      a buffer that is larger (by a factor of scale in each dimension)
++      than the desired surface size.
++
++      If scale is not positive the invalid_scale protocol error is
++      raised.
++      </description>
++      <arg name="scale" type="int"
++         summary="positive scale for interpreting buffer contents"/>
++    </request>
++
++    <!-- Version 4 additions -->
++    <request name="damage_buffer" since="4">
++      <description summary="mark part of the surface damaged using buffer coordinates">
++      This request is used to describe the regions where the pending
++      buffer is different from the current surface contents, and where
++      the surface therefore needs to be repainted. The compositor
++      ignores the parts of the damage that fall outside of the surface.
++
++      Damage is double-buffered state, see wl_surface.commit.
++
++      The damage rectangle is specified in buffer coordinates,
++      where x and y specify the upper left corner of the damage rectangle.
++
++      The initial value for pending damage is empty: no damage.
++      wl_surface.damage_buffer adds pending damage: the new pending
++      damage is the union of old pending damage and the given rectangle.
++
++      wl_surface.commit assigns pending damage as the current damage,
++      and clears pending damage. The server will clear the current
++      damage as it repaints the surface.
++
++      This request differs from wl_surface.damage in only one way - it
++      takes damage in buffer coordinates instead of surface-local
++      coordinates. While this generally is more intuitive than surface
++      coordinates, it is especially desirable when using wp_viewport
++      or when a drawing library (like EGL) is unaware of buffer scale
++      and buffer transform.
++
++      Note: Because buffer transformation changes and damage requests may
++      be interleaved in the protocol stream, it is impossible to determine
++      the actual mapping between surface and buffer damage until
++      wl_surface.commit time. Therefore, compositors wishing to take both
++      kinds of damage into account will have to accumulate damage from the
++      two requests separately and only transform from one to the other
++      after receiving the wl_surface.commit.
++      </description>
++      <arg name="x" type="int" summary="buffer-local x coordinate"/>
++      <arg name="y" type="int" summary="buffer-local y coordinate"/>
++      <arg name="width" type="int" summary="width of damage rectangle"/>
++      <arg name="height" type="int" summary="height of damage rectangle"/>
++    </request>
++   </interface>
++
++  <interface name="wl_seat" version="6">
++    <description summary="group of input devices">
++      A seat is a group of keyboards, pointer and touch devices. This
++      object is published as a global during start up, or when such a
++      device is hot plugged.  A seat typically has a pointer and
++      maintains a keyboard focus and a pointer focus.
++    </description>
++
++    <enum name="capability" bitfield="true">
++      <description summary="seat capability bitmask">
++      This is a bitmask of capabilities this seat has; if a member is
++      set, then it is present on the seat.
++      </description>
++      <entry name="pointer" value="1" summary="the seat has pointer devices"/>
++      <entry name="keyboard" value="2" summary="the seat has one or more keyboards"/>
++      <entry name="touch" value="4" summary="the seat has touch devices"/>
++    </enum>
++
++    <event name="capabilities">
++      <description summary="seat capabilities changed">
++      This is emitted whenever a seat gains or loses the pointer,
++      keyboard or touch capabilities.  The argument is a capability
++      enum containing the complete set of capabilities this seat has.
++
++      When the pointer capability is added, a client may create a
++      wl_pointer object using the wl_seat.get_pointer request. This object
++      will receive pointer events until the capability is removed in the
++      future.
++
++      When the pointer capability is removed, a client should destroy the
++      wl_pointer objects associated with the seat where the capability was
++      removed, using the wl_pointer.release request. No further pointer
++      events will be received on these objects.
++
++      In some compositors, if a seat regains the pointer capability and a
++      client has a previously obtained wl_pointer object of version 4 or
++      less, that object may start sending pointer events again. This
++      behavior is considered a misinterpretation of the intended behavior
++      and must not be relied upon by the client. wl_pointer objects of
++      version 5 or later must not send events if created before the most
++      recent event notifying the client of an added pointer capability.
++
++      The above behavior also applies to wl_keyboard and wl_touch with the
++      keyboard and touch capabilities, respectively.
++      </description>
++      <arg name="capabilities" type="uint" enum="capability" summary="capabilities of the seat"/>
++    </event>
++
++    <request name="get_pointer">
++      <description summary="return pointer object">
++      The ID provided will be initialized to the wl_pointer interface
++      for this seat.
++
++      This request only takes effect if the seat has the pointer
++      capability, or has had the pointer capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the pointer capability.
++      </description>
++      <arg name="id" type="new_id" interface="wl_pointer" summary="seat pointer"/>
++    </request>
++
++    <request name="get_keyboard">
++      <description summary="return keyboard object">
++      The ID provided will be initialized to the wl_keyboard interface
++      for this seat.
++
++      This request only takes effect if the seat has the keyboard
++      capability, or has had the keyboard capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the keyboard capability.
++      </description>
++      <arg name="id" type="new_id" interface="wl_keyboard" summary="seat keyboard"/>
++    </request>
++
++    <request name="get_touch">
++      <description summary="return touch object">
++      The ID provided will be initialized to the wl_touch interface
++      for this seat.
++
++      This request only takes effect if the seat has the touch
++      capability, or has had the touch capability in the past.
++      It is a protocol violation to issue this request on a seat that has
++      never had the touch capability.
++      </description>
++      <arg name="id" type="new_id" interface="wl_touch" summary="seat touch interface"/>
++    </request>
++
++    <!-- Version 2 additions -->
++
++    <event name="name" since="2">
++      <description summary="unique identifier for this seat">
++      In a multiseat configuration this can be used by the client to help
++      identify which physical devices the seat represents. Based on
++      the seat configuration used by the compositor.
++      </description>
++      <arg name="name" type="string" summary="seat identifier"/>
++    </event>
++
++    <!-- Version 5 additions -->
++
++    <request name="release" type="destructor" since="5">
++      <description summary="release the seat object">
++      Using this request a client can tell the server that it is not going to
++      use the seat object anymore.
++      </description>
++    </request>
++
++  </interface>
++
++  <interface name="wl_pointer" version="6">
++    <description summary="pointer input device">
++      The wl_pointer interface represents one or more input devices,
++      such as mice, which control the pointer location and pointer_focus
++      of a seat.
++
++      The wl_pointer interface generates motion, enter and leave
++      events for the surfaces that the pointer is located over,
++      and button and axis events for button presses, button releases
++      and scrolling.
++    </description>
++
++    <enum name="error">
++      <entry name="role" value="0" summary="given wl_surface has another role"/>
++    </enum>
++
++    <request name="set_cursor">
++      <description summary="set the pointer surface">
++      Set the pointer surface, i.e., the surface that contains the
++      pointer image (cursor). This request gives the surface the role
++      of a cursor. If the surface already has another role, it raises
++      a protocol error.
++
++      The cursor actually changes only if the pointer
++      focus for this device is one of the requesting client's surfaces
++      or the surface parameter is the current pointer surface. If
++      there was a previous surface set with this request it is
++      replaced. If surface is NULL, the pointer image is hidden.
++
++      The parameters hotspot_x and hotspot_y define the position of
++      the pointer surface relative to the pointer location. Its
++      top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
++      where (x, y) are the coordinates of the pointer location, in
++      surface-local coordinates.
++
++      On surface.attach requests to the pointer surface, hotspot_x
++      and hotspot_y are decremented by the x and y parameters
++      passed to the request. Attach must be confirmed by
++      wl_surface.commit as usual.
++
++      The hotspot can also be updated by passing the currently set
++      pointer surface to this request with new values for hotspot_x
++      and hotspot_y.
++
++      The current and pending input regions of the wl_surface are
++      cleared, and wl_surface.set_input_region is ignored until the
++      wl_surface is no longer used as the cursor. When the use as a
++      cursor ends, the current and pending input regions become
++      undefined, and the wl_surface is unmapped.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" allow-null="true"
++         summary="pointer surface"/>
++      <arg name="hotspot_x" type="int" summary="surface-local x coordinate"/>
++      <arg name="hotspot_y" type="int" summary="surface-local y coordinate"/>
++    </request>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notification that this seat's pointer is focused on a certain
++      surface.
++
++      When a seat's focus enters a surface, the pointer image
++      is undefined and a client should respond to this event by setting
++      an appropriate pointer image with the set_cursor request.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface entered by the pointer"/>
++      <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notification that this seat's pointer is no longer focused on
++      a certain surface.
++
++      The leave notification is sent before the enter notification
++      for the new focus.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the leave event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface left by the pointer"/>
++    </event>
++
++    <event name="motion">
++      <description summary="pointer motion event">
++      Notification of pointer location change. The arguments
++      surface_x and surface_y are the location relative to the
++      focused surface.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface_x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="surface_y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <enum name="button_state">
++      <description summary="physical button state">
++      Describes the physical state of a button that produced the button
++      event.
++      </description>
++      <entry name="released" value="0" summary="the button is not pressed"/>
++      <entry name="pressed" value="1" summary="the button is pressed"/>
++    </enum>
++
++    <event name="button">
++      <description summary="pointer button event">
++      Mouse button click and release notifications.
++
++      The location of the click is given by the last motion or
++      enter event.
++      The time argument is a timestamp with millisecond
++      granularity, with an undefined base.
++
++      The button is a button code as defined in the Linux kernel's
++      linux/input-event-codes.h header file, e.g. BTN_LEFT.
++
++      Any 16-bit button code value is reserved for future additions to the
++      kernel's event code list. All other button codes above 0xFFFF are
++      currently undefined but may be used in future versions of this
++      protocol.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the button event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="button" type="uint" summary="button that produced the event"/>
++      <arg name="state" type="uint" enum="button_state" summary="physical state of the button"/>
++    </event>
++
++    <enum name="axis">
++      <description summary="axis types">
++      Describes the axis types of scroll events.
++      </description>
++      <entry name="vertical_scroll" value="0" summary="vertical axis"/>
++      <entry name="horizontal_scroll" value="1" summary="horizontal axis"/>
++    </enum>
++
++    <event name="axis">
++      <description summary="axis event">
++      Scroll and other axis notifications.
++
++      For scroll events (vertical and horizontal scroll axes), the
++      value parameter is the length of a vector along the specified
++      axis in a coordinate space identical to those of motion events,
++      representing a relative movement along the specified axis.
++
++      For devices that support movements non-parallel to axes multiple
++      axis events will be emitted.
++
++      When applicable, for example for touch pads, the server can
++      choose to emit scroll events where the motion vector is
++      equivalent to a motion event vector.
++
++      When applicable, a client can transform its content relative to the
++      scroll distance.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++      <arg name="value" type="fixed" summary="length of vector in surface-local coordinate space"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the pointer object">
++      Using this request a client can tell the server that it is not going to
++      use the pointer object anymore.
++
++      This request destroys the pointer proxy object, so clients must not call
++      wl_pointer_destroy() after using this request.
++      </description>
++    </request>
++
++    <!-- Version 5 additions -->
++
++    <event name="frame" since="5">
++      <description summary="end of a pointer event sequence">
++      Indicates the end of a set of events that logically belong together.
++      A client is expected to accumulate the data in all events within the
++      frame before proceeding.
++
++      All wl_pointer events before a wl_pointer.frame event belong
++      logically together. For example, in a diagonal scroll motion the
++      compositor will send an optional wl_pointer.axis_source event, two
++      wl_pointer.axis events (horizontal and vertical) and finally a
++      wl_pointer.frame event. The client may use this information to
++      calculate a diagonal vector for scrolling.
++
++      When multiple wl_pointer.axis events occur within the same frame,
++      the motion vector is the combined motion of all events.
++      When a wl_pointer.axis and a wl_pointer.axis_stop event occur within
++      the same frame, this indicates that axis movement in one axis has
++      stopped but continues in the other axis.
++      When multiple wl_pointer.axis_stop events occur within the same
++      frame, this indicates that these axes stopped in the same instance.
++
++      A wl_pointer.frame event is sent for every logical event group,
++      even if the group only contains a single wl_pointer event.
++      Specifically, a client may get a sequence: motion, frame, button,
++      frame, axis, frame, axis_stop, frame.
++
++      The wl_pointer.enter and wl_pointer.leave events are logical events
++      generated by the compositor and not the hardware. These events are
++      also grouped by a wl_pointer.frame. When a pointer moves from one
++      surface to another, a compositor should group the
++      wl_pointer.leave event within the same wl_pointer.frame.
++      However, a client must not rely on wl_pointer.leave and
++      wl_pointer.enter being in the same wl_pointer.frame.
++      Compositor-specific policies may require the wl_pointer.leave and
++      wl_pointer.enter event being split across multiple wl_pointer.frame
++      groups.
++      </description>
++    </event>
++
++    <enum name="axis_source">
++      <description summary="axis source types">
++      Describes the source types for axis events. This indicates to the
++      client how an axis event was physically generated; a client may
++      adjust the user interface accordingly. For example, scroll events
++      from a "finger" source may be in a smooth coordinate space with
++      kinetic scrolling whereas a "wheel" source may be in discrete steps
++      of a number of lines.
++      </description>
++      <entry name="wheel" value="0" summary="a physical wheel rotation" />
++      <entry name="finger" value="1" summary="finger on a touch surface" />
++      <entry name="continuous" value="2">
++      <description summary="continuous coordinate space">
++        A device generating events in a continuous coordinate space, but
++        using something other than a finger. One example for this source
++        is button-based scrolling where the vertical motion of a device
++        is converted to scroll events while a button is held down.
++      </description>
++      </entry>
++      <entry name="wheel_tilt" value="3" since="6">
++      <description summary="a physical wheel tilt">
++        Indicates that the actual device is a wheel but the scroll event is
++        not caused by a rotation but a (usually sideways) tilt of the wheel.
++      </description>
++      </entry>
++    </enum>
++
++    <event name="axis_source" since="5">
++      <description summary="axis source event">
++      Source information for scroll and other axes.
++
++      This event does not occur on its own. It is sent before a
++      wl_pointer.frame event and carries the source information for
++      all events within that frame.
++
++      The source specifies how this event was generated. If the source is
++      wl_pointer.axis_source.finger, a wl_pointer.axis_stop event will be
++      sent when the user lifts the finger off the device.
++
++      If the source is wl_pointer.axis_source.wheel,
++      wl_pointer.axis_source.wheel_tilt or
++      wl_pointer.axis_source.continuous, a wl_pointer.axis_stop event may
++      or may not be sent. Whether a compositor sends an axis_stop event
++      for these sources is hardware-specific and implementation-dependent;
++      clients must not rely on receiving an axis_stop event for these
++      scroll sources and should treat scroll sequences from these scroll
++      sources as unterminated by default.
++
++      This event is optional. If the source is unknown for a particular
++      axis event sequence, no event is sent.
++      Only one wl_pointer.axis_source event is permitted per frame.
++
++      The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++      not guaranteed.
++      </description>
++      <arg name="axis_source" type="uint" enum="axis_source" summary="source of the axis event"/>
++    </event>
++
++    <event name="axis_stop" since="5">
++      <description summary="axis stop event">
++      Stop notification for scroll and other axes.
++
++      For some wl_pointer.axis_source types, a wl_pointer.axis_stop event
++      is sent to notify a client that the axis sequence has terminated.
++      This enables the client to implement kinetic scrolling.
++      See the wl_pointer.axis_source documentation for information on when
++      this event may be generated.
++
++      Any wl_pointer.axis events with the same axis_source after this
++      event should be considered as the start of a new axis motion.
++
++      The timestamp is to be interpreted identical to the timestamp in the
++      wl_pointer.axis event. The timestamp value may be the same as a
++      preceding wl_pointer.axis event.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="axis" type="uint" enum="axis" summary="the axis stopped with this event"/>
++    </event>
++
++    <event name="axis_discrete" since="5">
++      <description summary="axis click event">
++      Discrete step information for scroll and other axes.
++
++      This event carries the axis value of the wl_pointer.axis event in
++      discrete steps (e.g. mouse wheel clicks).
++
++      This event does not occur on its own, it is coupled with a
++      wl_pointer.axis event that represents this axis value on a
++      continuous scale. The protocol guarantees that each axis_discrete
++      event is always followed by exactly one axis event with the same
++      axis number within the same wl_pointer.frame. Note that the protocol
++      allows for other events to occur between the axis_discrete and
++      its coupled axis event, including other axis_discrete or axis
++      events.
++
++      This event is optional; continuous scrolling devices
++      like two-finger scrolling on touchpads do not have discrete
++      steps and do not generate this event.
++
++      The discrete value carries the directional information. e.g. a value
++      of -2 is two steps towards the negative direction of this axis.
++
++      The axis number is identical to the axis number in the associated
++      axis event.
++
++      The order of wl_pointer.axis_discrete and wl_pointer.axis_source is
++      not guaranteed.
++      </description>
++      <arg name="axis" type="uint" enum="axis" summary="axis type"/>
++      <arg name="discrete" type="int" summary="number of steps"/>
++    </event>
++  </interface>
++
++  <interface name="wl_keyboard" version="6">
++    <description summary="keyboard input device">
++      The wl_keyboard interface represents one or more keyboards
++      associated with a seat.
++    </description>
++
++    <enum name="keymap_format">
++      <description summary="keyboard mapping format">
++      This specifies the format of the keymap provided to the
++      client with the wl_keyboard.keymap event.
++      </description>
++      <entry name="no_keymap" value="0"
++           summary="no keymap; client must understand how to interpret the raw keycode"/>
++      <entry name="xkb_v1" value="1"
++           summary="libxkbcommon compatible; to determine the xkb keycode, clients must add 8 to the key event keycode"/>
++    </enum>
++
++    <event name="keymap">
++      <description summary="keyboard mapping">
++      This event provides a file descriptor to the client which can be
++      memory-mapped to provide a keyboard mapping description.
++      </description>
++      <arg name="format" type="uint" enum="keymap_format" summary="keymap format"/>
++      <arg name="fd" type="fd" summary="keymap file descriptor"/>
++      <arg name="size" type="uint" summary="keymap size, in bytes"/>
++    </event>
++
++    <event name="enter">
++      <description summary="enter event">
++      Notification that this seat's keyboard focus is on a certain
++      surface.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the enter event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface gaining keyboard focus"/>
++      <arg name="keys" type="array" summary="the currently pressed keys"/>
++    </event>
++
++    <event name="leave">
++      <description summary="leave event">
++      Notification that this seat's keyboard focus is no longer on
++      a certain surface.
++
++      The leave notification is sent before the enter notification
++      for the new focus.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the leave event"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface that lost keyboard focus"/>
++    </event>
++
++    <enum name="key_state">
++      <description summary="physical key state">
++      Describes the physical state of a key that produced the key event.
++      </description>
++      <entry name="released" value="0" summary="key is not pressed"/>
++      <entry name="pressed" value="1" summary="key is pressed"/>
++    </enum>
++
++    <event name="key">
++      <description summary="key event">
++      A key was pressed or released.
++      The time argument is a timestamp with millisecond
++      granularity, with an undefined base.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the key event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="key" type="uint" summary="key that produced the event"/>
++      <arg name="state" type="uint" enum="key_state" summary="physical state of the key"/>
++    </event>
++
++    <event name="modifiers">
++      <description summary="modifier and group state">
++      Notifies clients that the modifier and/or group state has
++      changed, and it should update its local state.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the modifiers event"/>
++      <arg name="mods_depressed" type="uint" summary="depressed modifiers"/>
++      <arg name="mods_latched" type="uint" summary="latched modifiers"/>
++      <arg name="mods_locked" type="uint" summary="locked modifiers"/>
++      <arg name="group" type="uint" summary="keyboard layout"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the keyboard object"/>
++    </request>
++
++    <!-- Version 4 additions -->
++
++    <event name="repeat_info" since="4">
++      <description summary="repeat rate and delay">
++      Informs the client about the keyboard's repeat rate and delay.
++
++      This event is sent as soon as the wl_keyboard object has been created,
++      and is guaranteed to be received by the client before any key press
++      event.
++
++      Negative values for either rate or delay are illegal. A rate of zero
++      will disable any repeating (regardless of the value of delay).
++
++      This event can be sent later on as well with a new value if necessary,
++      so clients should continue listening for the event past the creation
++      of wl_keyboard.
++      </description>
++      <arg name="rate" type="int"
++         summary="the rate of repeating keys in characters per second"/>
++      <arg name="delay" type="int"
++         summary="delay in milliseconds since key down until repeating starts"/>
++    </event>
++  </interface>
++
++  <interface name="wl_touch" version="6">
++    <description summary="touchscreen input device">
++      The wl_touch interface represents a touchscreen
++      associated with a seat.
++
++      Touch interactions can consist of one or more contacts.
++      For each contact, a series of events is generated, starting
++      with a down event, followed by zero or more motion events,
++      and ending with an up event. Events relating to the same
++      contact point can be identified by the ID of the sequence.
++    </description>
++
++    <event name="down">
++      <description summary="touch down event and beginning of a touch sequence">
++      A new touch point has appeared on the surface. This touch point is
++      assigned a unique ID. Future events from this touch point reference
++      this ID. The ID ceases to be valid after a touch up event and may be
++      reused in the future.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the touch down event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="surface" type="object" interface="wl_surface" summary="surface touched"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="up">
++      <description summary="end of a touch event sequence">
++      The touch point has disappeared. No further events will be sent for
++      this touch point and the touch point's ID is released and may be
++      reused in a future touch down event.
++      </description>
++      <arg name="serial" type="uint" summary="serial number of the touch up event"/>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++    </event>
++
++    <event name="motion">
++      <description summary="update of touch point coordinates">
++      A touch point has changed coordinates.
++      </description>
++      <arg name="time" type="uint" summary="timestamp with millisecond granularity"/>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="x" type="fixed" summary="surface-local x coordinate"/>
++      <arg name="y" type="fixed" summary="surface-local y coordinate"/>
++    </event>
++
++    <event name="frame">
++      <description summary="end of touch frame event">
++      Indicates the end of a set of events that logically belong together.
++      A client is expected to accumulate the data in all events within the
++      frame before proceeding.
++
++      A wl_touch.frame terminates at least one event but otherwise no
++      guarantee is provided about the set of events within a frame. A client
++      must assume that any state not updated in a frame is unchanged from the
++      previously known state.
++      </description>
++    </event>
++
++    <event name="cancel">
++      <description summary="touch session cancelled">
++      Sent if the compositor decides the touch stream is a global
++      gesture. No further events are sent to the clients from that
++      particular gesture. Touch cancellation applies to all touch points
++      currently active on this client's surface. The client is
++      responsible for finalizing the touch points, future touch points on
++      this surface may reuse the touch point ID.
++      </description>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the touch object"/>
++    </request>
++
++    <!-- Version 6 additions -->
++
++    <event name="shape" since="6">
++      <description summary="update shape of touch point">
++      Sent when a touchpoint has changed its shape.
++
++      This event does not occur on its own. It is sent before a
++      wl_touch.frame event and carries the new shape information for
++      any previously reported, or new touch points of that frame.
++
++      Other events describing the touch point such as wl_touch.down,
++      wl_touch.motion or wl_touch.orientation may be sent within the
++      same wl_touch.frame. A client should treat these events as a single
++      logical touch point update. The order of wl_touch.shape,
++      wl_touch.orientation and wl_touch.motion is not guaranteed.
++      A wl_touch.down event is guaranteed to occur before the first
++      wl_touch.shape event for this touch ID but both events may occur within
++      the same wl_touch.frame.
++
++      A touchpoint shape is approximated by an ellipse through the major and
++      minor axis length. The major axis length describes the longer diameter
++      of the ellipse, while the minor axis length describes the shorter
++      diameter. Major and minor are orthogonal and both are specified in
++      surface-local coordinates. The center of the ellipse is always at the
++      touchpoint location as reported by wl_touch.down or wl_touch.move.
++
++      This event is only sent by the compositor if the touch device supports
++      shape reports. The client has to make reasonable assumptions about the
++      shape if it did not receive this event.
++      </description>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="major" type="fixed" summary="length of the major axis in surface-local coordinates"/>
++      <arg name="minor" type="fixed" summary="length of the minor axis in surface-local coordinates"/>
++    </event>
++
++    <event name="orientation" since="6">
++      <description summary="update orientation of touch point">
++      Sent when a touchpoint has changed its orientation.
++
++      This event does not occur on its own. It is sent before a
++      wl_touch.frame event and carries the new shape information for
++      any previously reported, or new touch points of that frame.
++
++      Other events describing the touch point such as wl_touch.down,
++      wl_touch.motion or wl_touch.shape may be sent within the
++      same wl_touch.frame. A client should treat these events as a single
++      logical touch point update. The order of wl_touch.shape,
++      wl_touch.orientation and wl_touch.motion is not guaranteed.
++      A wl_touch.down event is guaranteed to occur before the first
++      wl_touch.orientation event for this touch ID but both events may occur
++      within the same wl_touch.frame.
++
++      The orientation describes the clockwise angle of a touchpoint's major
++      axis to the positive surface y-axis and is normalized to the -180 to
++      +180 degree range. The granularity of orientation depends on the touch
++      device, some devices only support binary rotation values between 0 and
++      90 degrees.
++
++      This event is only sent by the compositor if the touch device supports
++      orientation reports.
++      </description>
++      <arg name="id" type="int" summary="the unique ID of this touch point"/>
++      <arg name="orientation" type="fixed" summary="angle between major axis and positive surface y-axis in degrees"/>
++    </event>
++  </interface>
++
++  <interface name="wl_output" version="3">
++    <description summary="compositor output region">
++      An output describes part of the compositor geometry.  The
++      compositor works in the 'compositor coordinate system' and an
++      output corresponds to a rectangular area in that space that is
++      actually visible.  This typically corresponds to a monitor that
++      displays part of the compositor space.  This object is published
++      as global during start up, or when a monitor is hotplugged.
++    </description>
++
++    <enum name="subpixel">
++      <description summary="subpixel geometry information">
++      This enumeration describes how the physical
++      pixels on an output are laid out.
++      </description>
++      <entry name="unknown" value="0" summary="unknown geometry"/>
++      <entry name="none" value="1" summary="no geometry"/>
++      <entry name="horizontal_rgb" value="2" summary="horizontal RGB"/>
++      <entry name="horizontal_bgr" value="3" summary="horizontal BGR"/>
++      <entry name="vertical_rgb" value="4" summary="vertical RGB"/>
++      <entry name="vertical_bgr" value="5" summary="vertical BGR"/>
++    </enum>
++
++    <enum name="transform">
++      <description summary="transform from framebuffer to output">
++      This describes the transform that a compositor will apply to a
++      surface to compensate for the rotation or mirroring of an
++      output device.
++
++      The flipped values correspond to an initial flip around a
++      vertical axis followed by rotation.
++
++      The purpose is mainly to allow clients to render accordingly and
++      tell the compositor, so that for fullscreen surfaces, the
++      compositor will still be able to scan out directly from client
++      surfaces.
++      </description>
++      <entry name="normal" value="0" summary="no transform"/>
++      <entry name="90" value="1" summary="90 degrees counter-clockwise"/>
++      <entry name="180" value="2" summary="180 degrees counter-clockwise"/>
++      <entry name="270" value="3" summary="270 degrees counter-clockwise"/>
++      <entry name="flipped" value="4" summary="180 degree flip around a vertical axis"/>
++      <entry name="flipped_90" value="5" summary="flip and rotate 90 degrees counter-clockwise"/>
++      <entry name="flipped_180" value="6" summary="flip and rotate 180 degrees counter-clockwise"/>
++      <entry name="flipped_270" value="7" summary="flip and rotate 270 degrees counter-clockwise"/>
++    </enum>
++
++    <event name="geometry">
++      <description summary="properties of the output">
++      The geometry event describes geometric properties of the output.
++      The event is sent when binding to the output object and whenever
++      any of the properties change.
++      </description>
++      <arg name="x" type="int"
++         summary="x position within the global compositor space"/>
++      <arg name="y" type="int"
++         summary="y position within the global compositor space"/>
++      <arg name="physical_width" type="int"
++         summary="width in millimeters of the output"/>
++      <arg name="physical_height" type="int"
++         summary="height in millimeters of the output"/>
++      <arg name="subpixel" type="int" enum="subpixel"
++         summary="subpixel orientation of the output"/>
++      <arg name="make" type="string"
++         summary="textual description of the manufacturer"/>
++      <arg name="model" type="string"
++         summary="textual description of the model"/>
++      <arg name="transform" type="int" enum="transform"
++         summary="transform that maps framebuffer to output"/>
++    </event>
++
++    <enum name="mode" bitfield="true">
++      <description summary="mode information">
++      These flags describe properties of an output mode.
++      They are used in the flags bitfield of the mode event.
++      </description>
++      <entry name="current" value="0x1"
++           summary="indicates this is the current mode"/>
++      <entry name="preferred" value="0x2"
++           summary="indicates this is the preferred mode"/>
++    </enum>
++
++    <event name="mode">
++      <description summary="advertise available modes for the output">
++      The mode event describes an available mode for the output.
++
++      The event is sent when binding to the output object and there
++      will always be one mode, the current mode.  The event is sent
++      again if an output changes mode, for the mode that is now
++      current.  In other words, the current mode is always the last
++      mode that was received with the current flag set.
++
++      The size of a mode is given in physical hardware units of
++      the output device. This is not necessarily the same as
++      the output size in the global compositor space. For instance,
++      the output may be scaled, as described in wl_output.scale,
++      or transformed, as described in wl_output.transform.
++      </description>
++      <arg name="flags" type="uint" enum="mode" summary="bitfield of mode flags"/>
++      <arg name="width" type="int" summary="width of the mode in hardware units"/>
++      <arg name="height" type="int" summary="height of the mode in hardware units"/>
++      <arg name="refresh" type="int" summary="vertical refresh rate in mHz"/>
++    </event>
++
++    <!-- Version 2 additions -->
++
++    <event name="done" since="2">
++      <description summary="sent all information about output">
++      This event is sent after all other properties have been
++      sent after binding to the output object and after any
++      other property changes done after that. This allows
++      changes to the output properties to be seen as
++      atomic, even if they happen via multiple events.
++      </description>
++    </event>
++
++    <event name="scale" since="2">
++      <description summary="output scaling properties">
++      This event contains scaling geometry information
++      that is not in the geometry event. It may be sent after
++      binding the output object or if the output scale changes
++      later. If it is not sent, the client should assume a
++      scale of 1.
++
++      A scale larger than 1 means that the compositor will
++      automatically scale surface buffers by this amount
++      when rendering. This is used for very high resolution
++      displays where applications rendering at the native
++      resolution would be too small to be legible.
++
++      It is intended that scaling aware clients track the
++      current output of a surface, and if it is on a scaled
++      output it should use wl_surface.set_buffer_scale with
++      the scale of the output. That way the compositor can
++      avoid scaling the surface, and the client can supply
++      a higher detail image.
++      </description>
++      <arg name="factor" type="int" summary="scaling factor of output"/>
++    </event>
++
++    <!-- Version 3 additions -->
++
++    <request name="release" type="destructor" since="3">
++      <description summary="release the output object">
++      Using this request a client can tell the server that it is not going to
++      use the output object anymore.
++      </description>
++    </request>
++  </interface>
++
++  <interface name="wl_region" version="1">
++    <description summary="region interface">
++      A region object describes an area.
++
++      Region objects are used to describe the opaque and input
++      regions of a surface.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="destroy region">
++      Destroy the region.  This will invalidate the object ID.
++      </description>
++    </request>
++
++    <request name="add">
++      <description summary="add rectangle to region">
++      Add the specified rectangle to the region.
++      </description>
++      <arg name="x" type="int" summary="region-local x coordinate"/>
++      <arg name="y" type="int" summary="region-local y coordinate"/>
++      <arg name="width" type="int" summary="rectangle width"/>
++      <arg name="height" type="int" summary="rectangle height"/>
++    </request>
++
++    <request name="subtract">
++      <description summary="subtract rectangle from region">
++      Subtract the specified rectangle from the region.
++      </description>
++      <arg name="x" type="int" summary="region-local x coordinate"/>
++      <arg name="y" type="int" summary="region-local y coordinate"/>
++      <arg name="width" type="int" summary="rectangle width"/>
++      <arg name="height" type="int" summary="rectangle height"/>
++    </request>
++  </interface>
++
++  <interface name="wl_subcompositor" version="1">
++    <description summary="sub-surface compositing">
++      The global interface exposing sub-surface compositing capabilities.
++      A wl_surface, that has sub-surfaces associated, is called the
++      parent surface. Sub-surfaces can be arbitrarily nested and create
++      a tree of sub-surfaces.
++
++      The root surface in a tree of sub-surfaces is the main
++      surface. The main surface cannot be a sub-surface, because
++      sub-surfaces must always have a parent.
++
++      A main surface with its sub-surfaces forms a (compound) window.
++      For window management purposes, this set of wl_surface objects is
++      to be considered as a single window, and it should also behave as
++      such.
++
++      The aim of sub-surfaces is to offload some of the compositing work
++      within a window from clients to the compositor. A prime example is
++      a video player with decorations and video in separate wl_surface
++      objects. This should allow the compositor to pass YUV video buffer
++      processing to dedicated overlay hardware when possible.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="unbind from the subcompositor interface">
++      Informs the server that the client will not be using this
++      protocol object anymore. This does not affect any other
++      objects, wl_subsurface objects included.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="bad_surface" value="0"
++           summary="the to-be sub-surface is invalid"/>
++    </enum>
++
++    <request name="get_subsurface">
++      <description summary="give a surface the role sub-surface">
++      Create a sub-surface interface for the given surface, and
++      associate it with the given parent surface. This turns a
++      plain wl_surface into a sub-surface.
++
++      The to-be sub-surface must not already have another role, and it
++      must not have an existing wl_subsurface object. Otherwise a protocol
++      error is raised.
++      </description>
++      <arg name="id" type="new_id" interface="wl_subsurface"
++         summary="the new sub-surface object ID"/>
++      <arg name="surface" type="object" interface="wl_surface"
++         summary="the surface to be turned into a sub-surface"/>
++      <arg name="parent" type="object" interface="wl_surface"
++         summary="the parent surface"/>
++    </request>
++  </interface>
++
++  <interface name="wl_subsurface" version="1">
++    <description summary="sub-surface interface to a wl_surface">
++      An additional interface to a wl_surface object, which has been
++      made a sub-surface. A sub-surface has one parent surface. A
++      sub-surface's size and position are not limited to that of the parent.
++      Particularly, a sub-surface is not automatically clipped to its
++      parent's area.
++
++      A sub-surface becomes mapped, when a non-NULL wl_buffer is applied
++      and the parent surface is mapped. The order of which one happens
++      first is irrelevant. A sub-surface is hidden if the parent becomes
++      hidden, or if a NULL wl_buffer is applied. These rules apply
++      recursively through the tree of surfaces.
++
++      The behaviour of a wl_surface.commit request on a sub-surface
++      depends on the sub-surface's mode. The possible modes are
++      synchronized and desynchronized, see methods
++      wl_subsurface.set_sync and wl_subsurface.set_desync. Synchronized
++      mode caches the wl_surface state to be applied when the parent's
++      state gets applied, and desynchronized mode applies the pending
++      wl_surface state directly. A sub-surface is initially in the
++      synchronized mode.
++
++      Sub-surfaces have also other kind of state, which is managed by
++      wl_subsurface requests, as opposed to wl_surface requests. This
++      state includes the sub-surface position relative to the parent
++      surface (wl_subsurface.set_position), and the stacking order of
++      the parent and its sub-surfaces (wl_subsurface.place_above and
++      .place_below). This state is applied when the parent surface's
++      wl_surface state is applied, regardless of the sub-surface's mode.
++      As the exception, set_sync and set_desync are effective immediately.
++
++      The main surface can be thought to be always in desynchronized mode,
++      since it does not have a parent in the sub-surfaces sense.
++
++      Even if a sub-surface is in desynchronized mode, it will behave as
++      in synchronized mode, if its parent surface behaves as in
++      synchronized mode. This rule is applied recursively throughout the
++      tree of surfaces. This means, that one can set a sub-surface into
++      synchronized mode, and then assume that all its child and grand-child
++      sub-surfaces are synchronized, too, without explicitly setting them.
++
++      If the wl_surface associated with the wl_subsurface is destroyed, the
++      wl_subsurface object becomes inert. Note, that destroying either object
++      takes effect immediately. If you need to synchronize the removal
++      of a sub-surface to the parent surface update, unmap the sub-surface
++      first by attaching a NULL wl_buffer, update parent, and then destroy
++      the sub-surface.
++
++      If the parent wl_surface object is destroyed, the sub-surface is
++      unmapped.
++    </description>
++
++    <request name="destroy" type="destructor">
++      <description summary="remove sub-surface interface">
++      The sub-surface interface is removed from the wl_surface object
++      that was turned into a sub-surface with a
++      wl_subcompositor.get_subsurface request. The wl_surface's association
++      to the parent is deleted, and the wl_surface loses its role as
++      a sub-surface. The wl_surface is unmapped.
++      </description>
++    </request>
++
++    <enum name="error">
++      <entry name="bad_surface" value="0"
++           summary="wl_surface is not a sibling or the parent"/>
++    </enum>
++
++    <request name="set_position">
++      <description summary="reposition the sub-surface">
++      This schedules a sub-surface position change.
++      The sub-surface will be moved so that its origin (top left
++      corner pixel) will be at the location x, y of the parent surface
++      coordinate system. The coordinates are not restricted to the parent
++      surface area. Negative values are allowed.
++
++      The scheduled coordinates will take effect whenever the state of the
++      parent surface is applied. When this happens depends on whether the
++      parent surface is in synchronized mode or not. See
++      wl_subsurface.set_sync and wl_subsurface.set_desync for details.
++
++      If more than one set_position request is invoked by the client before
++      the commit of the parent surface, the position of a new request always
++      replaces the scheduled position from any previous request.
++
++      The initial position is 0, 0.
++      </description>
++      <arg name="x" type="int" summary="x coordinate in the parent surface"/>
++      <arg name="y" type="int" summary="y coordinate in the parent surface"/>
++    </request>
++
++    <request name="place_above">
++      <description summary="restack the sub-surface">
++      This sub-surface is taken from the stack, and put back just
++      above the reference surface, changing the z-order of the sub-surfaces.
++      The reference surface must be one of the sibling surfaces, or the
++      parent surface. Using any other surface, including this sub-surface,
++      will cause a protocol error.
++
++      The z-order is double-buffered. Requests are handled in order and
++      applied immediately to a pending state. The final pending state is
++      copied to the active state the next time the state of the parent
++      surface is applied. When this happens depends on whether the parent
++      surface is in synchronized mode or not. See wl_subsurface.set_sync and
++      wl_subsurface.set_desync for details.
++
++      A new sub-surface is initially added as the top-most in the stack
++      of its siblings and parent.
++      </description>
++      <arg name="sibling" type="object" interface="wl_surface"
++         summary="the reference surface"/>
++    </request>
++
++    <request name="place_below">
++      <description summary="restack the sub-surface">
++      The sub-surface is placed just below the reference surface.
++      See wl_subsurface.place_above.
++      </description>
++      <arg name="sibling" type="object" interface="wl_surface"
++         summary="the reference surface"/>
++    </request>
++
++    <request name="set_sync">
++      <description summary="set sub-surface to synchronized mode">
++      Change the commit behaviour of the sub-surface to synchronized
++      mode, also described as the parent dependent mode.
++
++      In synchronized mode, wl_surface.commit on a sub-surface will
++      accumulate the committed state in a cache, but the state will
++      not be applied and hence will not change the compositor output.
++      The cached state is applied to the sub-surface immediately after
++      the parent surface's state is applied. This ensures atomic
++      updates of the parent and all its synchronized sub-surfaces.
++      Applying the cached state will invalidate the cache, so further
++      parent surface commits do not (re-)apply old state.
++
++      See wl_subsurface for the recursive effect of this mode.
++      </description>
++    </request>
++
++    <request name="set_desync">
++      <description summary="set sub-surface to desynchronized mode">
++      Change the commit behaviour of the sub-surface to desynchronized
++      mode, also described as independent or freely running mode.
++
++      In desynchronized mode, wl_surface.commit on a sub-surface will
++      apply the pending state directly, without caching, as happens
++      normally with a wl_surface. Calling wl_surface.commit on the
++      parent surface has no effect on the sub-surface's wl_surface
++      state. This mode allows a sub-surface to be updated on its own.
++
++      If cached state exists when wl_surface.commit is called in
++      desynchronized mode, the pending state is added to the cached
++      state, and applied as a whole. This invalidates the cache.
++
++      Note: even if a sub-surface is set to desynchronized, a parent
++      sub-surface may override it to behave as synchronized. For details,
++      see wl_subsurface.
++
++      If a surface's parent surface behaves as desynchronized, then
++      the cached state is applied on set_desync.
++      </description>
++    </request>
++  </interface>
++
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..348d2dc2d2ff51c8e69dd238e5bd2cc8fb3da0f6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,196 @@@
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_CLIENT_PROTOCOL_H
++#define SMALL_TEST_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client-core.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++      /**
++       * this is the first
++       */
++      INTF_A_FOO_FIRST = 0,
++      /**
++       * this is the second
++       */
++      INTF_A_FOO_SECOND = 1,
++      /**
++       * this is the third
++       * @since 2
++       */
++      INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_listener
++ */
++struct intf_A_listener {
++      /**
++       */
++      void (*hey)(void *data,
++                  struct intf_A *intf_A);
++};
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline int
++intf_A_add_listener(struct intf_A *intf_A,
++                  const struct intf_A_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) intf_A,
++                                   (void (**)(void)) listener, data);
++}
++
++#define INTF_A_RQ1 0
++#define INTF_A_RQ2 1
++#define INTF_A_DESTROY 2
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_intf_A */
++static inline void
++intf_A_set_user_data(struct intf_A *intf_A, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data);
++}
++
++/** @ingroup iface_intf_A */
++static inline void *
++intf_A_get_user_data(struct intf_A *intf_A)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) intf_A);
++}
++
++static inline uint32_t
++intf_A_get_version(struct intf_A *intf_A)
++{
++      return wl_proxy_get_version((struct wl_proxy *) intf_A);
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void *
++intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version)
++{
++      struct wl_proxy *untyped_new;
++
++      untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_RQ1, interface, version, 0, interface->name, version, NULL);
++
++      return (void *) untyped_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline struct intf_not_here *
++intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj)
++{
++      struct wl_proxy *typed_new;
++
++      typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj);
++
++      return (struct intf_not_here *) typed_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void
++intf_A_destroy(struct intf_A *intf_A)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8c6abc500e29aa0d848b4ff42b57a54682162d35
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,196 @@@
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_CLIENT_PROTOCOL_H
++#define SMALL_TEST_CLIENT_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-client.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++      /**
++       * this is the first
++       */
++      INTF_A_FOO_FIRST = 0,
++      /**
++       * this is the second
++       */
++      INTF_A_FOO_SECOND = 1,
++      /**
++       * this is the third
++       * @since 2
++       */
++      INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_listener
++ */
++struct intf_A_listener {
++      /**
++       */
++      void (*hey)(void *data,
++                  struct intf_A *intf_A);
++};
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline int
++intf_A_add_listener(struct intf_A *intf_A,
++                  const struct intf_A_listener *listener, void *data)
++{
++      return wl_proxy_add_listener((struct wl_proxy *) intf_A,
++                                   (void (**)(void)) listener, data);
++}
++
++#define INTF_A_RQ1 0
++#define INTF_A_RQ2 1
++#define INTF_A_DESTROY 2
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/** @ingroup iface_intf_A */
++static inline void
++intf_A_set_user_data(struct intf_A *intf_A, void *user_data)
++{
++      wl_proxy_set_user_data((struct wl_proxy *) intf_A, user_data);
++}
++
++/** @ingroup iface_intf_A */
++static inline void *
++intf_A_get_user_data(struct intf_A *intf_A)
++{
++      return wl_proxy_get_user_data((struct wl_proxy *) intf_A);
++}
++
++static inline uint32_t
++intf_A_get_version(struct intf_A *intf_A)
++{
++      return wl_proxy_get_version((struct wl_proxy *) intf_A);
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void *
++intf_A_rq1(struct intf_A *intf_A, const struct wl_interface *interface, uint32_t version)
++{
++      struct wl_proxy *untyped_new;
++
++      untyped_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_RQ1, interface, version, 0, interface->name, version, NULL);
++
++      return (void *) untyped_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline struct intf_not_here *
++intf_A_rq2(struct intf_A *intf_A, const char *str, int32_t i, uint32_t u, wl_fixed_t f, int32_t fd, struct another_intf *obj)
++{
++      struct wl_proxy *typed_new;
++
++      typed_new = wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_RQ2, &intf_not_here_interface, wl_proxy_get_version((struct wl_proxy *) intf_A), 0, NULL, str, i, u, f, fd, obj);
++
++      return (struct intf_not_here *) typed_new;
++}
++
++/**
++ * @ingroup iface_intf_A
++ */
++static inline void
++intf_A_destroy(struct intf_A *intf_A)
++{
++      wl_proxy_marshal_flags((struct wl_proxy *) intf_A,
++                       INTF_A_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) intf_A), WL_MARSHAL_FLAG_DESTROY);
++}
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bd6d33de9517d39377dc2afccac78f0c545d9df8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,61 @@@
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++      NULL,
++      &intf_not_here_interface,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++      { "rq1", "sun", small_test_types + 0 },
++      { "rq2", "nsiufho", small_test_types + 1 },
++      { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++      { "hey", "", small_test_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface intf_A_interface = {
++      "intf_A", 3,
++      3, intf_A_requests,
++      1, intf_A_events,
++};
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bd6d33de9517d39377dc2afccac78f0c545d9df8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,61 @@@
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++      NULL,
++      &intf_not_here_interface,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++      { "rq1", "sun", small_test_types + 0 },
++      { "rq2", "nsiufho", small_test_types + 1 },
++      { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++      { "hey", "", small_test_types + 0 },
++};
++
++WL_EXPORT const struct wl_interface intf_A_interface = {
++      "intf_A", 3,
++      3, intf_A_requests,
++      1, intf_A_events,
++};
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fe035ffe26219090ad8d8e311726d8788fc108f6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,71 @@@
++/* SCANNER TEST */
++
++/*
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include "wayland-util.h"
++
++#ifndef __has_attribute
++# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */
++#endif
++
++#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
++#define WL_PRIVATE __attribute__ ((visibility("hidden")))
++#else
++#define WL_PRIVATE
++#endif
++
++extern const struct wl_interface another_intf_interface;
++extern const struct wl_interface intf_not_here_interface;
++
++static const struct wl_interface *small_test_types[] = {
++      NULL,
++      &intf_not_here_interface,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      NULL,
++      &another_intf_interface,
++};
++
++static const struct wl_message intf_A_requests[] = {
++      { "rq1", "sun", small_test_types + 0 },
++      { "rq2", "nsiufho", small_test_types + 1 },
++      { "destroy", "", small_test_types + 0 },
++};
++
++static const struct wl_message intf_A_events[] = {
++      { "hey", "", small_test_types + 0 },
++};
++
++WL_PRIVATE const struct wl_interface intf_A_interface = {
++      "intf_A", 3,
++      3, intf_A_requests,
++      1, intf_A_events,
++};
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f0fd1f90d3b4b74e26f37cd2e505e3fcd465eb66
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,157 @@@
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_SERVER_PROTOCOL_H
++#define SMALL_TEST_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server-core.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++      /**
++       * this is the first
++       */
++      INTF_A_FOO_FIRST = 0,
++      /**
++       * this is the second
++       */
++      INTF_A_FOO_SECOND = 1,
++      /**
++       * this is the third
++       * @since 2
++       */
++      INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_interface
++ */
++struct intf_A_interface {
++      /**
++       * @param interface name of the objects interface
++       * @param version version of the objects interface
++       */
++      void (*rq1)(struct wl_client *client,
++                  struct wl_resource *resource,
++                  const char *interface, uint32_t version, uint32_t untyped_new);
++      /**
++       */
++      void (*rq2)(struct wl_client *client,
++                  struct wl_resource *resource,
++                  uint32_t typed_new,
++                  const char *str,
++                  int32_t i,
++                  uint32_t u,
++                  wl_fixed_t f,
++                  int32_t fd,
++                  struct wl_resource *obj);
++      /**
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define INTF_A_HEY 0
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ * Sends an hey event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++intf_A_send_hey(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, INTF_A_HEY);
++}
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..22b8113336062f4f43b2f927ae142e01eb5eb56d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,157 @@@
++/* SCANNER TEST */
++
++#ifndef SMALL_TEST_SERVER_PROTOCOL_H
++#define SMALL_TEST_SERVER_PROTOCOL_H
++
++#include <stdint.h>
++#include <stddef.h>
++#include "wayland-server.h"
++
++#ifdef  __cplusplus
++extern "C" {
++#endif
++
++struct wl_client;
++struct wl_resource;
++
++/**
++ * @page page_small_test The small_test protocol
++ * @section page_ifaces_small_test Interfaces
++ * - @subpage page_iface_intf_A - the thing A
++ * @section page_copyright_small_test Copyright
++ * <pre>
++ *
++ * Copyright © 2016 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person
++ * obtaining a copy of this software and associated documentation files
++ * (the "Software"), to deal in the Software without restriction,
++ * including without limitation the rights to use, copy, modify, merge,
++ * publish, distribute, sublicense, and/or sell copies of the Software,
++ * and to permit persons to whom the Software is furnished to do so,
++ * subject to the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ * </pre>
++ */
++struct another_intf;
++struct intf_A;
++struct intf_not_here;
++
++#ifndef INTF_A_INTERFACE
++#define INTF_A_INTERFACE
++/**
++ * @page page_iface_intf_A intf_A
++ * @section page_iface_intf_A_desc Description
++ *
++ * A useless example trying to tickle the scanner.
++ * @section page_iface_intf_A_api API
++ * See @ref iface_intf_A.
++ */
++/**
++ * @defgroup iface_intf_A The intf_A interface
++ *
++ * A useless example trying to tickle the scanner.
++ */
++extern const struct wl_interface intf_A_interface;
++#endif
++
++#ifndef INTF_A_FOO_ENUM
++#define INTF_A_FOO_ENUM
++enum intf_A_foo {
++      /**
++       * this is the first
++       */
++      INTF_A_FOO_FIRST = 0,
++      /**
++       * this is the second
++       */
++      INTF_A_FOO_SECOND = 1,
++      /**
++       * this is the third
++       * @since 2
++       */
++      INTF_A_FOO_THIRD = 2,
++};
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_FOO_THIRD_SINCE_VERSION 2
++#endif /* INTF_A_FOO_ENUM */
++
++/**
++ * @ingroup iface_intf_A
++ * @struct intf_A_interface
++ */
++struct intf_A_interface {
++      /**
++       * @param interface name of the objects interface
++       * @param version version of the objects interface
++       */
++      void (*rq1)(struct wl_client *client,
++                  struct wl_resource *resource,
++                  const char *interface, uint32_t version, uint32_t untyped_new);
++      /**
++       */
++      void (*rq2)(struct wl_client *client,
++                  struct wl_resource *resource,
++                  uint32_t typed_new,
++                  const char *str,
++                  int32_t i,
++                  uint32_t u,
++                  wl_fixed_t f,
++                  int32_t fd,
++                  struct wl_resource *obj);
++      /**
++       */
++      void (*destroy)(struct wl_client *client,
++                      struct wl_resource *resource);
++};
++
++#define INTF_A_HEY 0
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_HEY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ1_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_RQ2_SINCE_VERSION 1
++/**
++ * @ingroup iface_intf_A
++ */
++#define INTF_A_DESTROY_SINCE_VERSION 1
++
++/**
++ * @ingroup iface_intf_A
++ * Sends an hey event to the client owning the resource.
++ * @param resource_ The client's resource
++ */
++static inline void
++intf_A_send_hey(struct wl_resource *resource_)
++{
++      wl_resource_post_event(resource_, INTF_A_HEY);
++}
++
++#ifdef  __cplusplus
++}
++#endif
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..832ed0e1261e836b582468ebfa66ff0f71656b20
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,58 @@@
++<?xml version="1.0" encoding="UTF-8"?>
++<protocol name="small_test">
++
++  <copyright>
++    Copyright © 2016 Collabora, Ltd.
++
++    Permission is hereby granted, free of charge, to any person
++    obtaining a copy of this software and associated documentation files
++    (the "Software"), to deal in the Software without restriction,
++    including without limitation the rights to use, copy, modify, merge,
++    publish, distribute, sublicense, and/or sell copies of the Software,
++    and to permit persons to whom the Software is furnished to do so,
++    subject to the following conditions:
++
++    The above copyright notice and this permission notice (including the
++    next paragraph) shall be included in all copies or substantial
++    portions of the Software.
++
++    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++    NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++    CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++    SOFTWARE.
++  </copyright>
++
++  <interface name="intf_A" version="3">
++    <description summary="the thing A">
++      A useless example trying to tickle the scanner.
++    </description>
++
++    <request name="rq1">
++      <arg name="untyped_new" type="new_id"/>
++    </request>
++
++    <request name="rq2">
++      <arg name="typed_new" type="new_id" interface="intf_not_here"/>
++      <arg name="str" type="string"/>
++      <arg name="i" type="int"/>
++      <arg name="u" type="uint"/>
++      <arg name="f" type="fixed"/>
++      <arg name="fd" type="fd"/>
++      <arg name="obj" type="object" interface="another_intf"/>
++    </request>
++
++    <request name="destroy" type="destructor"/>
++
++    <event name="hey"/>
++
++    <enum name="foo">
++      <entry name="first" value="0" summary="this is the first"/>
++      <entry name="second" value="1" summary="this is the second"/>
++      <entry name="third" value="2" since="2" summary="this is the third"/>
++    </enum>
++  </interface>
++</protocol>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..bcb3267f90fc0446bdf4f12564938291a3c773d5
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1712 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ * Copyright © 2013 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdbool.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdarg.h>
++#include <stdint.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++
++#include <pthread.h>
++#include <poll.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "wayland-client.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++#include "tests-server-protocol.h"
++#include "tests-client-protocol.h"
++
++struct display_destroy_listener {
++      struct wl_listener listener;
++      int done;
++};
++
++static void
++display_destroy_notify(struct wl_listener *l, void *data)
++{
++      struct display_destroy_listener *listener;
++
++      listener = wl_container_of(l, listener, listener);
++      listener->done = 1;
++}
++
++TEST(display_destroy_listener)
++{
++      struct wl_display *display;
++      struct display_destroy_listener a, b;
++
++      display = wl_display_create();
++      assert(display);
++
++      a.listener.notify = &display_destroy_notify;
++      a.done = 0;
++      wl_display_add_destroy_listener(display, &a.listener);
++
++      assert(wl_display_get_destroy_listener(display, display_destroy_notify) ==
++             &a.listener);
++
++      b.listener.notify = display_destroy_notify;
++      b.done = 0;
++      wl_display_add_destroy_listener(display, &b.listener);
++
++      wl_list_remove(&a.listener.link);
++
++      wl_display_destroy(display);
++
++      assert(!a.done);
++      assert(b.done);
++}
++
++/* Fake 'client' which does not use wl_display_connect, and thus leaves the
++ * file descriptor passed through WAYLAND_SOCKET intact. This should not
++ * trigger an assertion in the leak check. */
++static void
++empty_client(void)
++{
++      return;
++}
++
++TEST(tc_leaks_tests)
++{
++      struct display *d = display_create();
++      client_create_noarg(d, empty_client);
++      display_run(d);
++      display_destroy(d);
++}
++
++/* This is how pre proxy-version registry binds worked,
++ * this should create a proxy that shares the display's
++ * version number: 0 */
++static void *
++old_registry_bind(struct wl_registry *wl_registry,
++                uint32_t name,
++                const struct wl_interface *interface,
++                uint32_t version)
++{
++      struct wl_proxy *id;
++
++      id = wl_proxy_marshal_constructor(
++              (struct wl_proxy *) wl_registry, WL_REGISTRY_BIND,
++              interface, name, interface->name, version, NULL);
++
++      return (void *) id;
++}
++
++struct handler_info {
++      struct wl_seat *seat;
++      uint32_t bind_version;
++      bool use_unversioned;
++};
++
++static void
++registry_handle_globals(void *data, struct wl_registry *registry,
++                      uint32_t id, const char *intf, uint32_t ver)
++{
++      struct handler_info *hi = data;
++
++      /* This is only for the proxy version test */
++      if (hi->bind_version)
++              ver = hi->bind_version;
++
++      if (strcmp(intf, "wl_seat") == 0) {
++              if (hi->use_unversioned)
++                      hi->seat = old_registry_bind(registry, id,
++                                                   &wl_seat_interface, ver);
++              else
++                      hi->seat = wl_registry_bind(registry, id,
++                                                  &wl_seat_interface, ver);
++              assert(hi->seat);
++      }
++}
++
++static const struct wl_registry_listener registry_listener = {
++      registry_handle_globals,
++      NULL
++};
++
++static struct wl_seat *
++client_get_seat_with_info(struct client *c, struct handler_info *hi)
++{
++      struct wl_registry *reg = wl_display_get_registry(c->wl_display);
++      assert(reg);
++
++      assert(hi);
++      hi->seat = NULL;
++      wl_registry_add_listener(reg, &registry_listener, hi);
++      wl_display_roundtrip(c->wl_display);
++      assert(hi->seat);
++
++      wl_registry_destroy(reg);
++
++      return hi->seat;
++}
++
++static struct wl_seat *
++client_get_seat(struct client *c)
++{
++      struct handler_info hi;
++
++      hi.use_unversioned = false;
++      hi.bind_version = 0;
++
++      return client_get_seat_with_info(c, &hi);
++}
++
++static void
++check_pending_error(struct client *c, struct wl_proxy *proxy)
++{
++      uint32_t ec, id;
++      int err;
++      const struct wl_interface *intf;
++
++      err = wl_display_get_error(c->wl_display);
++      assert(err == EPROTO);
++
++      ec = wl_display_get_protocol_error(c->wl_display, &intf, &id);
++      assert(ec == 23);
++      assert(intf == &wl_seat_interface);
++      assert(id == wl_proxy_get_id(proxy));
++}
++
++static void
++check_for_error(struct client *c, struct wl_proxy *proxy)
++{
++      /* client should be disconnected */
++      assert(wl_display_roundtrip(c->wl_display) == -1);
++
++      check_pending_error(c, proxy);
++}
++
++static struct client_info *
++find_client_info(struct display *d, struct wl_client *client)
++{
++      struct client_info *ci;
++
++      wl_list_for_each(ci, &d->clients, link) {
++              if (ci->wl_client == client)
++                      return ci;
++      }
++
++      return NULL;
++}
++
++static void
++bind_seat(struct wl_client *client, void *data,
++        uint32_t vers, uint32_t id)
++{
++      struct display *d = data;
++      struct client_info *ci;
++      struct wl_resource *res;
++
++      ci = find_client_info(d, client);
++      assert(ci);
++
++      res = wl_resource_create(client, &wl_seat_interface, vers, id);
++      assert(res);
++
++      /* save the resource as client's info data,
++       * so that we can use it later */
++      ci->data = res;
++}
++
++static void
++client_disconnect_nocheck(struct client *c)
++{
++      wl_proxy_destroy((struct wl_proxy *) c->tc);
++      wl_display_disconnect(c->wl_display);
++      free(c);
++}
++
++static void
++post_error_main(void)
++{
++      struct client *c = client_connect();
++      struct wl_seat *seat = client_get_seat(c);
++
++      /* stop display so that it can post the error.
++       * The function should return -1, because of the posted error */
++      assert(stop_display(c, 1) == -1);
++
++      /* display should have posted error, check it! */
++      check_for_error(c, (struct wl_proxy *) seat);
++
++      /* don't call client_disconnect(c), because then the test would be
++       * aborted due to checks for error in this function */
++      wl_proxy_destroy((struct wl_proxy *) seat);
++      client_disconnect_nocheck(c);
++}
++
++TEST(post_error_to_one_client)
++{
++      struct display *d = display_create();
++      struct client_info *cl;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      cl = client_create_noarg(d, post_error_main);
++      display_run(d);
++
++      /* the display was stopped by client, so it can
++       * proceed in the code and post an error */
++      assert(cl->data);
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             23, "Dummy error");
++
++      /* this one should be ignored */
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             21, "Dummy error (ignore)");
++
++      display_resume(d);
++      display_destroy(d);
++}
++
++static void
++post_error_main2(void)
++{
++      struct client *c = client_connect();
++      struct wl_seat *seat = client_get_seat(c);
++
++      /* the error should not be posted for this client */
++      assert(stop_display(c, 2) >= 0);
++
++      wl_proxy_destroy((struct wl_proxy *) seat);
++      client_disconnect(c);
++}
++
++static void
++post_error_main3(void)
++{
++      struct client *c = client_connect();
++      struct wl_seat *seat = client_get_seat(c);
++
++      assert(stop_display(c, 2) == -1);
++      check_for_error(c, (struct wl_proxy *) seat);
++
++      /* don't call client_disconnect(c), because then the test would be
++       * aborted due to checks for error in this function */
++      wl_proxy_destroy((struct wl_proxy *) seat);
++      client_disconnect_nocheck(c);
++}
++
++/* all the testcases could be in one TEST, but splitting it
++ * apart is better for debugging when the test fails */
++TEST(post_error_to_one_from_two_clients)
++{
++      struct display *d = display_create();
++      struct client_info *cl;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      client_create_noarg(d, post_error_main2);
++      cl = client_create_noarg(d, post_error_main3);
++      display_run(d);
++
++      /* post error only to the second client */
++      assert(cl->data);
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             23, "Dummy error");
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             21, "Dummy error (ignore)");
++
++      display_resume(d);
++      display_destroy(d);
++}
++
++/* all the testcases could be in one TEST, but splitting it
++ * apart is better for debugging when the test fails */
++TEST(post_error_to_two_clients)
++{
++      struct display *d = display_create();
++      struct client_info *cl, *cl2;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      cl = client_create_noarg(d, post_error_main3);
++      cl2 = client_create_noarg(d, post_error_main3);
++
++      display_run(d);
++
++      /* Try to send the error to both clients */
++      assert(cl->data && cl2->data);
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             23, "Dummy error");
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             21, "Dummy error (ignore)");
++
++      wl_resource_post_error((struct wl_resource *) cl2->data,
++                             23, "Dummy error");
++      wl_resource_post_error((struct wl_resource *) cl2->data,
++                             21, "Dummy error (ignore)");
++
++      display_resume(d);
++      display_destroy(d);
++}
++
++static void
++post_nomem_main(void)
++{
++      struct client *c = client_connect();
++      struct wl_seat *seat = client_get_seat(c);
++
++      assert(stop_display(c, 1) == -1);
++      assert(wl_display_get_error(c->wl_display) == ENOMEM);
++
++      wl_proxy_destroy((struct wl_proxy *) seat);
++      client_disconnect_nocheck(c);
++}
++
++TEST(post_nomem_tst)
++{
++      struct display *d = display_create();
++      struct client_info *cl;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      cl = client_create_noarg(d, post_nomem_main);
++      display_run(d);
++
++      assert(cl->data);
++      wl_resource_post_no_memory((struct wl_resource *) cl->data);
++      display_resume(d);
++
++      /* first client terminated. Run it again,
++       * but post no memory to client */
++      cl = client_create_noarg(d, post_nomem_main);
++      display_run(d);
++
++      assert(cl->data);
++      wl_client_post_no_memory(cl->wl_client);
++      display_resume(d);
++
++      display_destroy(d);
++}
++
++static void
++post_implementation_error_main(void)
++{
++      struct client *c = client_connect();
++      struct wl_seat *seat = client_get_seat(c);
++      uint32_t object_id, protocol_error;
++      const struct wl_interface *interface;
++
++      assert(stop_display(c, 1) == -1);
++      int err = wl_display_get_error(c->wl_display);
++      fprintf(stderr, "Err is %i\n", err);
++      assert(err == EPROTO);
++      protocol_error = wl_display_get_protocol_error(c->wl_display,
++                                                     &interface,
++                                                     &object_id);
++      assert(protocol_error == WL_DISPLAY_ERROR_IMPLEMENTATION);
++      assert(interface == &wl_display_interface);
++
++      wl_proxy_destroy((struct wl_proxy *) seat);
++      client_disconnect_nocheck(c);
++}
++
++TEST(post_internal_error_tst)
++{
++      struct display *d = display_create();
++      struct client_info *cl;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      cl = client_create_noarg(d, post_implementation_error_main);
++      display_run(d);
++
++      wl_client_post_implementation_error(cl->wl_client, "Error %i", 20);
++
++      display_resume(d);
++
++      display_destroy(d);
++}
++
++static void
++register_reading(struct wl_display *display)
++{
++      while(wl_display_prepare_read(display) != 0 && errno == EAGAIN)
++              assert(wl_display_dispatch_pending(display) >= 0);
++      assert(wl_display_flush(display) >= 0);
++}
++
++/* create thread that will call prepare+read so that
++ * it will block */
++static pthread_t
++create_thread(struct client *c, void *(*func)(void*))
++{
++      pthread_t thread;
++
++      c->display_stopped = 0;
++      /* func must set display->stopped to 1 before sleeping */
++      assert(pthread_create(&thread, NULL, func, c) == 0);
++
++      /* make sure the thread is sleeping. It's a little bit racy
++       * (setting display_stopped to 1 and calling wl_display_read_events)
++       * so call usleep once again after the loop ends - it should
++       * be sufficient... */
++      while (c->display_stopped == 0)
++              test_usleep(500);
++      test_usleep(10000);
++
++      return thread;
++}
++
++static void *
++thread_read_error(void *data)
++{
++      struct client *c = data;
++
++      register_reading(c->wl_display);
++
++      /*
++       * Calling the read right now will block this thread
++       * until the other thread will read the data.
++       * However, after invoking an error, this
++       * thread should be woken up or it will block indefinitely.
++       */
++      c->display_stopped = 1;
++      assert(wl_display_read_events(c->wl_display) == -1);
++
++      assert(wl_display_dispatch_pending(c->wl_display) == -1);
++      assert(wl_display_get_error(c->wl_display));
++
++      pthread_exit(NULL);
++}
++
++/* test posting an error in multi-threaded environment. */
++static void
++threading_post_err(void)
++{
++      DISABLE_LEAK_CHECKS;
++
++      struct client *c = client_connect();
++      pthread_t thread;
++
++      /* register read intention */
++      register_reading(c->wl_display);
++
++      /* use this var as an indicator that thread is sleeping */
++      c->display_stopped = 0;
++
++      /* create new thread that will register its intention too */
++      thread = create_thread(c, thread_read_error);
++
++      /* so now we have sleeping thread waiting for a pthread_cond signal.
++       * The main thread must call wl_display_read_events().
++       * If this call fails, then it won't call broadcast at the
++       * end of the function and the sleeping thread will block indefinitely.
++       * Make the call fail and watch if libwayland will unblock the thread! */
++
++      /* create error on fd, so that wl_display_read_events will fail.
++       * The same can happen when server hangs up */
++      close(wl_display_get_fd(c->wl_display));
++      /* this read events will fail and will
++       * post an error that should wake the sleeping thread
++       * and dispatch the incoming events */
++      assert(wl_display_read_events(c->wl_display) == -1);
++
++      /* kill test in 3 seconds. This should be enough time for the
++       * thread to exit if it's not blocking. If everything is OK, than
++       * the thread was woken up and the test will end before the SIGALRM */
++      test_set_timeout(3);
++      pthread_join(thread, NULL);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(threading_errors_tst)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, threading_post_err);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void *
++thread_prepare_and_read(void *data)
++{
++      struct client *c = data;
++
++      register_reading(c->wl_display);
++
++      c->display_stopped = 1;
++
++      assert(wl_display_read_events(c->wl_display) == 0);
++      assert(wl_display_dispatch_pending(c->wl_display) == 0);
++
++      pthread_exit(NULL);
++}
++
++/* test cancel read*/
++static void
++threading_cancel_read(void)
++{
++      DISABLE_LEAK_CHECKS;
++
++      struct client *c = client_connect();
++      pthread_t th1, th2, th3;
++
++      register_reading(c->wl_display);
++
++      th1 = create_thread(c, thread_prepare_and_read);
++      th2 = create_thread(c, thread_prepare_and_read);
++      th3 = create_thread(c, thread_prepare_and_read);
++
++      /* all the threads are sleeping, waiting until read or cancel
++       * is called. Cancel the read and let the threads proceed */
++      wl_display_cancel_read(c->wl_display);
++
++      /* kill test in 3 seconds. This should be enough time for the
++       * thread to exit if it's not blocking. If everything is OK, than
++       * the thread was woken up and the test will end before the SIGALRM */
++      test_set_timeout(3);
++      pthread_join(th1, NULL);
++      pthread_join(th2, NULL);
++      pthread_join(th3, NULL);
++
++      client_disconnect(c);
++}
++
++TEST(threading_cancel_read_tst)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, threading_cancel_read);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void
++threading_read_eagain(void)
++{
++      DISABLE_LEAK_CHECKS;
++
++      struct client *c = client_connect();
++      pthread_t th1, th2, th3;
++
++      register_reading(c->wl_display);
++
++      th1 = create_thread(c, thread_prepare_and_read);
++      th2 = create_thread(c, thread_prepare_and_read);
++      th3 = create_thread(c, thread_prepare_and_read);
++
++      /* All the threads are sleeping, waiting until read or cancel
++       * is called. Since we have no data on socket waiting,
++       * the wl_connection_read should end up with error and set errno
++       * to EAGAIN. Check if the threads are woken up in this case. */
++      assert(wl_display_read_events(c->wl_display) == 0);
++      /* errno should be still set to EAGAIN if wl_connection_read
++       * set it - check if we're testing the right case */
++      assert(errno == EAGAIN);
++
++      test_set_timeout(3);
++      pthread_join(th1, NULL);
++      pthread_join(th2, NULL);
++      pthread_join(th3, NULL);
++
++      client_disconnect(c);
++}
++
++TEST(threading_read_eagain_tst)
++{
++      struct display *d = display_create();
++      client_create_noarg(d, threading_read_eagain);
++
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void *
++thread_prepare_and_read2(void *data)
++{
++      struct client *c = data;
++
++      while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
++              assert(wl_display_dispatch_pending(c->wl_display) == -1);
++      assert(wl_display_flush(c->wl_display) == -1);
++
++      c->display_stopped = 1;
++
++      assert(wl_display_read_events(c->wl_display) == -1);
++      assert(wl_display_dispatch_pending(c->wl_display) == -1);
++
++      pthread_exit(NULL);
++}
++
++static void
++threading_read_after_error(void)
++{
++      DISABLE_LEAK_CHECKS;
++
++      struct client *c = client_connect();
++      pthread_t thread;
++
++      /* create an error */
++      close(wl_display_get_fd(c->wl_display));
++      assert(wl_display_dispatch(c->wl_display) == -1);
++
++      /* try to prepare for reading */
++      while(wl_display_prepare_read(c->wl_display) != 0 && errno == EAGAIN)
++              assert(wl_display_dispatch_pending(c->wl_display) == -1);
++      assert(wl_display_flush(c->wl_display) == -1);
++
++      assert(pthread_create(&thread, NULL,
++                            thread_prepare_and_read2, c) == 0);
++
++      /* make sure thread is sleeping */
++      while (c->display_stopped == 0)
++              test_usleep(500);
++      test_usleep(10000);
++
++      assert(wl_display_read_events(c->wl_display) == -1);
++
++      /* kill test in 3 seconds */
++      test_set_timeout(3);
++      pthread_join(thread, NULL);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(threading_read_after_error_tst)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, threading_read_after_error);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void
++wait_for_error_using_dispatch(struct client *c, struct wl_proxy *proxy)
++{
++      int ret;
++
++      while (true) {
++              /* Dispatching should eventually hit the protocol error before
++               * any other error. */
++              ret = wl_display_dispatch(c->wl_display);
++              if (ret == 0) {
++                      continue;
++              } else {
++                      assert(errno == EPROTO);
++                      break;
++              }
++      }
++
++      check_pending_error(c, proxy);
++}
++
++static void
++wait_for_error_using_prepare_read(struct client *c, struct wl_proxy *proxy)
++{
++      int ret = 0;
++      struct pollfd pfd[2];
++
++      while (true) {
++              while (wl_display_prepare_read(c->wl_display) != 0 &&
++                    errno == EAGAIN) {
++                      assert(wl_display_dispatch_pending(c->wl_display) >= 0);
++              }
++
++              /* Flush may fail due to EPIPE if the connection is broken, but
++               * this must not set a fatal display error because that would
++               * result in it being impossible to read a potential protocol
++               * error. */
++              do {
++                      ret = wl_display_flush(c->wl_display);
++              } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
++              assert(ret >= 0 || errno == EPIPE);
++              assert(wl_display_get_error(c->wl_display) == 0);
++
++              pfd[0].fd = wl_display_get_fd(c->wl_display);
++              pfd[0].events = POLLIN;
++              do {
++                      ret = poll(pfd, 1, -1);
++              } while (ret == -1 && errno == EINTR);
++              assert(ret != -1);
++
++              /* We should always manage to read the error before the EPIPE
++               * comes this way. */
++              assert(wl_display_read_events(c->wl_display) == 0);
++
++              /* Dispatching should eventually hit the protocol error before
++               * any other error. */
++              ret = wl_display_dispatch_pending(c->wl_display);
++              if (ret == 0) {
++                      continue;
++              } else {
++                      assert(errno == EPROTO);
++                      break;
++              }
++      }
++
++      check_pending_error(c, proxy);
++}
++
++static void
++check_error_after_epipe(void *data)
++{
++      bool use_dispatch_helpers = *(bool *) data;
++      struct client *client;
++      struct wl_seat *seat;
++      struct wl_callback *callback;
++
++      client = client_connect();
++
++      /* This will, according to the implementation below, cause the server
++       * to post an error. */
++      seat = client_get_seat(client);
++      wl_display_flush(client->wl_display);
++
++      /* The server will not actually destroy the client until it receives
++       * input, so send something to trigger the client destruction. */
++      callback = wl_display_sync(client->wl_display);
++      wl_callback_destroy(callback);
++
++      /* Sleep some to give the server a chance to react and destroy the
++       * client. */
++      test_usleep(200000);
++
++      /* Wait for the protocol error and check that we reached it before
++       * EPIPE. */
++      if (use_dispatch_helpers) {
++              wait_for_error_using_dispatch(client, (struct wl_proxy *) seat);
++      } else {
++              wait_for_error_using_prepare_read(client,
++                                                (struct wl_proxy *) seat);
++      }
++
++      wl_seat_destroy(seat);
++      client_disconnect_nocheck(client);
++}
++
++static void
++bind_seat_and_post_error(struct wl_client *client, void *data,
++                       uint32_t version, uint32_t id)
++{
++      struct display *d = data;
++      struct client_info *ci;
++      struct wl_resource *resource;
++
++      ci = find_client_info(d, client);
++      assert(ci);
++
++      resource = wl_resource_create(client, &wl_seat_interface, version, id);
++      assert(resource);
++      ci->data = resource;
++
++      wl_resource_post_error(ci->data, 23, "Dummy error");
++}
++
++TEST(error_code_after_epipe)
++{
++      struct display *d = display_create();
++      bool use_dispatch_helpers;
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat_and_post_error);
++
++      use_dispatch_helpers = true;
++      client_create(d, check_error_after_epipe, &use_dispatch_helpers);
++      display_run(d);
++
++      use_dispatch_helpers = false;
++      client_create(d, check_error_after_epipe, &use_dispatch_helpers);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void
++check_seat_versions(struct wl_seat *seat, uint32_t ev)
++{
++      struct wl_pointer *pointer;
++
++      assert(wl_proxy_get_version((struct wl_proxy *) seat) == ev);
++      assert(wl_seat_get_version(seat) == ev);
++
++      pointer = wl_seat_get_pointer(seat);
++      assert(wl_pointer_get_version(pointer) == ev);
++      assert(wl_proxy_get_version((struct wl_proxy *) pointer) == ev);
++      wl_proxy_destroy((struct wl_proxy *) pointer);
++}
++
++/* Normal client with proxy versions available. */
++static void
++seat_version(void *data)
++{
++      struct handler_info *hi = data;
++      struct client *c = client_connect();
++      struct wl_seat *seat;
++
++      /* display proxy should always be version 0 */
++      assert(wl_proxy_get_version((struct wl_proxy *) c->wl_display) == 0);
++
++      seat = client_get_seat_with_info(c, hi);
++      if (hi->use_unversioned)
++              check_seat_versions(seat, 0);
++      else
++              check_seat_versions(seat, hi->bind_version);
++
++      wl_proxy_destroy((struct wl_proxy *) seat);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(versions)
++{
++      struct display *d = display_create();
++      struct wl_global *global;
++      int i;
++
++      global = wl_global_create(d->wl_display, &wl_seat_interface,
++                                5, d, bind_seat);
++
++      for (i = 1; i <= 5; i++) {
++              struct handler_info hi;
++
++              hi.bind_version = i;
++              hi.use_unversioned = false;
++              client_create(d, seat_version, &hi);
++              hi.use_unversioned = true;
++              client_create(d, seat_version, &hi);
++      }
++
++      display_run(d);
++
++      wl_global_destroy(global);
++
++      display_destroy(d);
++}
++
++static void
++check_error_on_destroyed_object(void *data)
++{
++      struct client *c;
++      struct wl_seat *seat;
++      uint32_t id;
++      const struct wl_interface *intf;
++
++      c = client_connect();
++      seat = client_get_seat(c);
++
++      /* destroy the seat proxy. The display won't know
++       * about it yet, so it will post the error as usual */
++      wl_proxy_destroy((struct wl_proxy *) seat);
++
++      /* let display post the error. The error will
++       * be caught in stop_display while dispatching */
++      assert(stop_display(c, 1) == -1);
++
++      /* check the returned error. Since the object was destroyed,
++       * we don't know the interface and id */
++      assert(wl_display_get_error(c->wl_display) == EPROTO);
++      assert(wl_display_get_protocol_error(c->wl_display, &intf, &id) == 23);
++      assert(intf == NULL);
++      assert(id == 0);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(error_on_destroyed_object)
++{
++      struct client_info *cl;
++      struct display *d = display_create();
++
++      wl_global_create(d->wl_display, &wl_seat_interface,
++                       1, d, bind_seat);
++
++      cl = client_create_noarg(d, check_error_on_destroyed_object);
++      display_run(d);
++
++      /* did client bind to the seat? */
++      assert(cl->data);
++
++      /* post error on the destroyed object */
++      wl_resource_post_error((struct wl_resource *) cl->data,
++                             23, "Dummy error");
++      display_resume(d);
++      display_destroy(d);
++}
++
++static bool
++global_filter(const struct wl_client *client,
++            const struct wl_global *global,
++            void *data)
++{
++      /* Hide the wl_data_offer interface if no data was provided */
++      if (wl_global_get_interface(global) == &wl_data_offer_interface)
++              return data != NULL;
++
++      /* Show all the others */
++      return true;
++}
++
++static void
++bind_data_offer(struct wl_client *client, void *data,
++              uint32_t vers, uint32_t id)
++{
++      /* Client should not be able to bind to this interface! */
++      assert(false);
++}
++
++static void
++registry_handle_filtered(void *data, struct wl_registry *registry,
++                       uint32_t id, const char *intf, uint32_t ver)
++{
++      uint32_t *name = data;
++
++      if (strcmp (intf, "wl_data_offer") == 0) {
++              assert(name);
++              *name = id;
++      }
++}
++
++static void
++registry_handle_remove_filtered(void *data, struct wl_registry *registry,
++                              uint32_t id)
++{
++      assert(false);
++}
++
++static const struct wl_registry_listener registry_listener_filtered = {
++      registry_handle_filtered,
++      registry_handle_remove_filtered,
++};
++
++static void
++get_globals(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry, &registry_listener_filtered, data);
++      wl_display_roundtrip(c->wl_display);
++
++      wl_registry_destroy(registry);
++      client_disconnect_nocheck(c);
++}
++
++TEST(filtered_global_is_hidden)
++{
++      struct display *d;
++      struct wl_global *g;
++
++      d = display_create();
++
++      g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++                    1, d, bind_data_offer);
++      wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++      client_create_noarg(d, get_globals);
++      display_run(d);
++
++      wl_global_destroy(g);
++
++      display_destroy(d);
++}
++
++static void
++get_dynamic_globals(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry, &registry_listener_filtered, data);
++      wl_display_roundtrip(c->wl_display);
++
++      /* Wait for the server to create a new global */
++      assert(stop_display(c, 1) >= 0);
++
++      /* Check that we don't see it */
++      wl_display_roundtrip(c->wl_display);
++
++      /* Wait for the server to remove that global */
++      assert(stop_display(c, 1) >= 0);
++
++      /* Check that we don't get a global_remove event */
++      wl_display_roundtrip(c->wl_display);
++
++      wl_registry_destroy(registry);
++      client_disconnect_nocheck(c);
++}
++
++TEST(filtered_dynamic_global_is_hidden)
++{
++      struct display *d;
++      struct wl_global *g;
++
++      d = display_create();
++      wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++      /* Create a client and let it enumerate the globals */
++      client_create_noarg(d, get_dynamic_globals);
++      display_run(d);
++
++      /* Dynamically create a new global */
++      g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++                           1, d, bind_data_offer);
++
++      display_resume(d);
++
++      /* Dynamically remove the global */
++      wl_global_destroy(g);
++
++      display_resume(d);
++
++      display_destroy(d);
++}
++
++static void
++check_bind_error(struct client *c)
++{
++      uint32_t errorcode, id;
++      int err;
++      const struct wl_interface *intf;
++
++      err = wl_display_get_error(c->wl_display);
++      assert(err == EPROTO);
++
++      errorcode = wl_display_get_protocol_error(c->wl_display, &intf, &id);
++      assert(errorcode == WL_DISPLAY_ERROR_INVALID_OBJECT);
++}
++
++static void
++force_bind(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++      void *ptr;
++      uint32_t *name = data;
++
++      registry = wl_display_get_registry(c->wl_display);
++
++      ptr = wl_registry_bind (registry, *name, &wl_data_offer_interface, 1);
++      wl_display_roundtrip(c->wl_display);
++      check_bind_error(c);
++
++      wl_proxy_destroy((struct wl_proxy *) ptr);
++      wl_registry_destroy(registry);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(bind_fails_on_filtered_global)
++{
++      struct display *d;
++      struct wl_global *g;
++      uint32_t *name;
++
++      /* Create a anonymous shared memory to pass the interface name */
++      name = mmap(NULL, sizeof(uint32_t),
++                  PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
++
++      d = display_create();
++
++      g = wl_global_create(d->wl_display, &wl_data_offer_interface,
++                           1, d, bind_data_offer);
++      wl_display_set_global_filter(d->wl_display, global_filter, name);
++
++      client_create(d, get_globals, name);
++      *name = 0;
++
++      display_run(d);
++      /* wl_data_offer should be 2 */
++      assert(*name == 2);
++      wl_display_set_global_filter(d->wl_display, global_filter, NULL);
++
++      /* Try to bind to the interface name when a global filter is in place */
++      client_create(d, force_bind, name);
++      display_run(d);
++
++      wl_global_destroy(g);
++
++      display_destroy(d);
++}
++
++static void
++pre_fd(void *data, struct fd_passer *fdp)
++{
++      fd_passer_destroy(fdp);
++}
++
++static void
++fd(void *data, struct fd_passer *fdp, int32_t fd)
++{
++      /* We destroyed the resource before this event */
++      assert(false);
++}
++
++struct fd_passer_listener fd_passer_listener = {
++      pre_fd,
++      fd,
++};
++
++static void
++zombie_fd_handle_globals(void *data, struct wl_registry *registry,
++                       uint32_t id, const char *intf, uint32_t ver)
++{
++      struct fd_passer *fdp;
++
++      if (!strcmp(intf, "fd_passer")) {
++              fdp = wl_registry_bind(registry, id, &fd_passer_interface, 1);
++              fd_passer_add_listener(fdp, &fd_passer_listener, NULL);
++      }
++}
++
++static const struct wl_registry_listener zombie_fd_registry_listener = {
++      zombie_fd_handle_globals,
++      NULL
++};
++
++static void
++zombie_client(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry, &zombie_fd_registry_listener, NULL);
++
++      /* Gets the registry */
++      wl_display_roundtrip(c->wl_display);
++
++      /* push out the fd_passer bind */
++      wl_display_roundtrip(c->wl_display);
++
++      /* push out our fd_passer.destroy */
++      wl_display_roundtrip(c->wl_display);
++
++      wl_registry_destroy(registry);
++
++      client_disconnect_nocheck(c);
++}
++
++struct passer_data {
++      struct wl_resource *conjoined_passer;
++};
++
++static void
++feed_pipe(int fd, char tosend)
++{
++      int count;
++
++      do {
++              count = write(fd, &tosend, 1);
++      } while (count != 1 && errno == EAGAIN);
++      assert(count == 1);
++      close(fd);
++}
++
++static void
++fd_passer_clobber(struct wl_client *client, struct wl_resource *res)
++{
++      struct passer_data *pdata = wl_resource_get_user_data(res);
++      int pipes1[2], pipes2[2], ret;
++
++      if (pdata->conjoined_passer) {
++              ret = pipe(pipes1);
++              assert(ret == 0);
++              ret = pipe(pipes2);
++              assert(ret == 0);
++
++              wl_resource_queue_event(res, FD_PASSER_FD, pipes1[0]);
++              fd_passer_send_fd(pdata->conjoined_passer, pipes2[0]);
++              feed_pipe(pipes1[1], '1');
++              feed_pipe(pipes2[1], '2');
++              close(pipes1[0]);
++              close(pipes2[0]);
++      }
++      wl_resource_destroy(res);
++}
++
++static void
++fd_passer_twin(struct wl_client *client, struct wl_resource *res, struct wl_resource *passer)
++{
++      struct passer_data *pdata = wl_resource_get_user_data(res);
++
++      pdata->conjoined_passer = passer;
++}
++
++static const struct fd_passer_interface fdp_interface = {
++      fd_passer_clobber,
++      fd_passer_twin
++};
++
++static void
++pdata_destroy(struct wl_resource *res)
++{
++      struct passer_data *pdata = wl_resource_get_user_data(res);
++
++      free(pdata);
++}
++
++static void
++bind_fd_passer(struct wl_client *client, void *data,
++             uint32_t vers, uint32_t id)
++{
++      struct wl_resource *res;
++      struct passer_data *pdata;
++
++      pdata = malloc(sizeof(*pdata));
++      assert(pdata);
++      pdata->conjoined_passer = NULL;
++
++      res = wl_resource_create(client, &fd_passer_interface, vers, id);
++      wl_resource_set_implementation(res, &fdp_interface, pdata, pdata_destroy);
++      assert(res);
++      if (vers == 1) {
++              fd_passer_send_pre_fd(res);
++              fd_passer_send_fd(res, fileno(stdin));
++      }
++}
++
++TEST(zombie_fd)
++{
++      struct display *d;
++      struct wl_global *g;
++
++      d = display_create();
++
++      g = wl_global_create(d->wl_display, &fd_passer_interface,
++                           1, d, bind_fd_passer);
++
++      client_create_noarg(d, zombie_client);
++      display_run(d);
++
++      wl_global_destroy(g);
++
++      display_destroy(d);
++}
++
++
++static void
++double_pre_fd(void *data, struct fd_passer *fdp)
++{
++      assert(false);
++}
++
++static void
++double_fd(void *data, struct fd_passer *fdp, int32_t fd)
++{
++      char buf;
++      int count;
++
++      do {
++              count = read(fd, &buf, 1);
++      } while (count != 1 && errno == EAGAIN);
++      assert(count == 1);
++
++      close(fd);
++      fd_passer_destroy(fdp);
++      assert(buf == '2');
++}
++
++struct fd_passer_listener double_fd_passer_listener = {
++      double_pre_fd,
++      double_fd,
++};
++
++
++static void
++double_zombie_fd_handle_globals(void *data, struct wl_registry *registry,
++                       uint32_t id, const char *intf, uint32_t ver)
++{
++      struct fd_passer *fdp1, *fdp2;
++
++      if (!strcmp(intf, "fd_passer")) {
++              fdp1 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
++              fd_passer_add_listener(fdp1, &double_fd_passer_listener, NULL);
++              fdp2 = wl_registry_bind(registry, id, &fd_passer_interface, 2);
++              fd_passer_add_listener(fdp2, &double_fd_passer_listener, NULL);
++              fd_passer_conjoin(fdp1, fdp2);
++              fd_passer_destroy(fdp1);
++      }
++}
++
++static const struct wl_registry_listener double_zombie_fd_registry_listener = {
++      double_zombie_fd_handle_globals,
++      NULL
++};
++
++static void
++double_zombie_client(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry, &double_zombie_fd_registry_listener, NULL);
++
++      /* Gets the registry */
++      wl_display_roundtrip(c->wl_display);
++
++      /* One more so server can respond to conjoin+destroy */
++      wl_display_roundtrip(c->wl_display);
++
++      /* And finally push out our last fd_passer.destroy */
++      wl_display_roundtrip(c->wl_display);
++
++      wl_registry_destroy(registry);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(zombie_fd_errant_consumption)
++{
++      struct display *d;
++      struct wl_global *g;
++
++      d = display_create();
++
++      g = wl_global_create(d->wl_display, &fd_passer_interface,
++                           2, d, bind_fd_passer);
++
++      client_create_noarg(d, double_zombie_client);
++      display_run(d);
++
++      wl_global_destroy(g);
++
++      display_destroy(d);
++}
++
++
++static void
++registry_bind_interface_mismatch_handle_global(void *data,
++                                             struct wl_registry *registry,
++                                             uint32_t id, const char *intf,
++                                             uint32_t ver)
++{
++      uint32_t *seat_id_ptr = data;
++
++      if (strcmp(intf, wl_seat_interface.name) == 0) {
++              *seat_id_ptr = id;
++      }
++}
++
++static const struct wl_registry_listener bind_interface_mismatch_registry_listener = {
++      registry_bind_interface_mismatch_handle_global,
++      NULL
++};
++
++static void
++registry_bind_interface_mismatch_client(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++      uint32_t seat_id = 0;
++      void *ptr;
++      int ret;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry,
++                               &bind_interface_mismatch_registry_listener,
++                               &seat_id);
++
++      ret = wl_display_roundtrip(c->wl_display);
++      assert(ret >= 0);
++      assert(seat_id != 0);
++
++      /* Bind with a different interface */
++      ptr = wl_registry_bind(registry, seat_id, &wl_output_interface, 1);
++      ret = wl_display_roundtrip(c->wl_display);
++      assert(ret < 0);
++      check_bind_error(c);
++
++      wl_proxy_destroy((struct wl_proxy *) ptr);
++      wl_registry_destroy(registry);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(registry_bind_interface_mismatch)
++{
++      struct display *d;
++      struct wl_global *seat_global;
++
++      d = display_create();
++
++      seat_global = wl_global_create(d->wl_display, &wl_seat_interface,
++                                     1, NULL, NULL);
++
++      client_create_noarg(d, registry_bind_interface_mismatch_client);
++      display_run(d);
++
++      wl_global_destroy(seat_global);
++
++      display_destroy(d);
++}
++
++static void
++send_overflow_client(void *data)
++{
++      struct client *c = client_connect();
++      int i, err = 0;
++      int *pipes = data;
++      char tmp = '\0';
++      int sock, optval = 16384;
++
++      /* Limit the send buffer size for the display socket to guarantee
++       * that the test will cause an overflow. */
++      sock = wl_display_get_fd(c->wl_display);
++      assert(setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &optval, sizeof(optval)) == 0);
++
++      /* Request to break out of 'display_run' in the main process */
++      assert(stop_display(c, 1) >= 0);
++
++      /* On Linux, the actual socket data + metadata space is twice `optval`;
++       * since each noop request requires 8 bytes, the buffer should overflow
++       * within <=4096 iterations. */
++      for (i = 0; i < 1000000; i++) {
++              noop_request(c);
++              err = wl_display_get_error(c->wl_display);
++              if (err)
++                      break;
++      }
++
++      /* Do not close the pipe file descriptors afterwards, because the leak
++       * check verifies that the initial/final FD counts are the same */
++      assert(write(pipes[1], &tmp, sizeof(tmp)) == (ssize_t)sizeof(tmp));
++
++      /* Expect an error */
++      fprintf(stderr, "Send loop failed on try %d, err = %d, %s\n", i, err, strerror(err));
++      assert(err == EAGAIN);
++
++      client_disconnect_nocheck(c);
++}
++
++TEST(send_overflow_disconnection)
++{
++      struct display *d;
++      char tmp;
++      int rpipe[2];
++      ssize_t ret;
++
++      assert(pipe(rpipe) != -1);
++
++      d = display_create();
++
++      (void) client_create(d, send_overflow_client, &rpipe);
++
++      /* Close write end of the pipe, so that the later read() call gets
++       * interrupted if the client dies */
++      close(rpipe[1]);
++
++      /* Run the display until the client sends a `stop_display`, then
++       * send a resume message but don't actually look at new messages */
++      display_run(d);
++      display_post_resume_events(d);
++      wl_display_flush_clients(d->wl_display);
++
++      /* Wait until all noop requests have been sent (read returns 1), or
++       * until client process aborts (read returns 0) */
++      do {
++              ret = read(rpipe[0], &tmp, sizeof(tmp));
++      } while (ret == -1 && errno == EINTR);
++      assert(ret != -1);
++      close(rpipe[0]);
++
++      /* For a clean shutdown */
++      display_run(d);
++
++      display_destroy(d);
++}
++
++static void
++registry_global_remove_before_handle_global(void *data,
++                                          struct wl_registry *registry,
++                                          uint32_t id, const char *intf,
++                                          uint32_t ver)
++{
++      uint32_t *id_ptr = data;
++
++      if (strcmp(intf, wl_seat_interface.name) == 0) {
++              assert(*id_ptr == 0);
++              *id_ptr = id;
++      }
++}
++
++static void
++registry_global_remove_before_handle_global_remove(void *data,
++                                                 struct wl_registry *registry,
++                                                 uint32_t id)
++{
++      uint32_t *id_ptr = data;
++
++      if (*id_ptr == id) {
++              *id_ptr = 0;
++      }
++}
++
++/* This listener expects a uint32_t user data pointer, sets it to the wl_seat
++ * global ID when receiving a "global" event, and sets it to zero when receiving
++ * a "global_remove" event. */
++static const struct wl_registry_listener global_remove_before_registry_listener = {
++      registry_global_remove_before_handle_global,
++      registry_global_remove_before_handle_global_remove,
++};
++
++static void
++global_remove_before_client(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++      uint32_t global_id = 0, saved_global_id;
++      struct wl_seat *seat;
++      int ret;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry,
++                               &global_remove_before_registry_listener,
++                               &global_id);
++
++      ret = wl_display_roundtrip(c->wl_display);
++      assert(ret >= 0);
++      assert(global_id != 0);
++      saved_global_id = global_id;
++
++      /* Wait for the compositor to remove the global */
++      assert(stop_display(c, 1) >= 0);
++
++      /* Check binding still works after the global has been removed. Also
++       * check we get the global_remove event. */
++      seat = wl_registry_bind(registry, saved_global_id, &wl_seat_interface, 1);
++      ret = wl_display_roundtrip(c->wl_display);
++      assert(ret >= 0);
++      assert(global_id == 0);
++
++      wl_seat_destroy(seat);
++      wl_registry_destroy(registry);
++
++      client_disconnect(c);
++}
++
++static void
++registry_global_remove_after_handle_global(void *data,
++                                         struct wl_registry *registry,
++                                         uint32_t id, const char *intf,
++                                         uint32_t ver)
++{
++      /* Make sure the global isn't advertised anymore after being removed */
++      assert(strcmp(intf, wl_seat_interface.name) != 0);
++}
++
++static const struct wl_registry_listener global_remove_after_registry_listener = {
++      registry_global_remove_after_handle_global,
++      NULL,
++};
++
++static void
++global_remove_after_client(void *data)
++{
++      struct client *c = client_connect();
++      struct wl_registry *registry;
++      uint32_t global_id = 0;
++      int ret;
++
++      registry = wl_display_get_registry(c->wl_display);
++      wl_registry_add_listener(registry,
++                               &global_remove_after_registry_listener,
++                               &global_id);
++
++      ret = wl_display_roundtrip(c->wl_display);
++      assert(ret >= 0);
++
++      wl_registry_destroy(registry);
++
++      client_disconnect(c);
++}
++
++TEST(global_remove)
++{
++      struct display *d;
++      struct wl_global *global;
++
++      d = display_create();
++
++      global = wl_global_create(d->wl_display, &wl_seat_interface,
++                                1, d, bind_seat);
++
++      /* Create a client before removing the global */
++      client_create_noarg(d, global_remove_before_client);
++
++      display_run(d);
++
++      wl_global_remove(global);
++
++      /* Create another client after removing the global */
++      client_create_noarg(d, global_remove_after_client);
++
++      display_resume(d);
++
++      wl_global_destroy(global);
++
++      display_destroy(d);
++}
++
++static void
++terminate_display(void *arg)
++{
++      struct wl_display *wl_display = arg;
++      wl_display_terminate(wl_display);
++}
++
++TEST(no_source_terminate)
++{
++      struct display *d;
++      struct wl_event_loop *loop;
++
++      d = display_create();
++      loop = wl_display_get_event_loop(d->wl_display);
++
++      wl_event_loop_add_idle(loop, terminate_display, d->wl_display);
++
++      display_run(d);
++      display_destroy(d);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a51ba8fb888ec534b52fb573b9eea5219dd968ee
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,555 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ * Copyright © 2012 Jason Ekstrand
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include <unistd.h>
++#include <signal.h>
++#include <string.h>
++#include <sys/time.h>
++
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++static int
++fd_dispatch(int fd, uint32_t mask, void *data)
++{
++      int *p = data;
++
++      assert(mask == 0);
++      ++(*p);
++
++      return 0;
++}
++
++TEST(event_loop_post_dispatch_check)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct wl_event_source *source;
++      int dispatch_ran = 0;
++      int p[2];
++
++      assert(loop);
++      assert(pipe(p) == 0);
++
++      source = wl_event_loop_add_fd(loop, p[0], WL_EVENT_READABLE,
++                                    fd_dispatch, &dispatch_ran);
++      assert(source);
++      wl_event_source_check(source);
++
++      wl_event_loop_dispatch(loop, 0);
++      assert(dispatch_ran == 1);
++
++      assert(close(p[0]) == 0);
++      assert(close(p[1]) == 0);
++      wl_event_source_remove(source);
++      wl_event_loop_destroy(loop);
++}
++
++struct free_source_context {
++      struct wl_event_source *source1, *source2;
++      int p1[2], p2[2];
++      int count;
++};
++
++static int
++free_source_callback(int fd, uint32_t mask, void *data)
++{
++      struct free_source_context *context = data;
++
++      context->count++;
++
++      /* Remove other source */
++      if (fd == context->p1[0]) {
++              wl_event_source_remove(context->source2);
++              context->source2 = NULL;
++      } else if (fd == context->p2[0]) {
++              wl_event_source_remove(context->source1);
++              context->source1 = NULL;
++      } else {
++              assert(0);
++      }
++
++      return 1;
++}
++
++TEST(event_loop_free_source_with_data)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct free_source_context context;
++      int data;
++
++      /* This test is a little tricky to get right, since we don't
++       * have any guarantee from the event loop (ie epoll) on the
++       * order of which it reports events.  We want to have one
++       * source free the other, but we don't know which one is going
++       * to run first.  So we add two fd sources with a callback
++       * that frees the other source and check that only one of them
++       * run (and that we don't crash, of course).
++       */
++
++      assert(loop);
++
++      context.count = 0;
++      assert(pipe(context.p1) == 0);
++      assert(pipe(context.p2) == 0);
++      context.source1 =
++              wl_event_loop_add_fd(loop, context.p1[0], WL_EVENT_READABLE,
++                                   free_source_callback, &context);
++      assert(context.source1);
++      context.source2 =
++              wl_event_loop_add_fd(loop, context.p2[0], WL_EVENT_READABLE,
++                                   free_source_callback, &context);
++      assert(context.source2);
++
++      data = 5;
++      assert(write(context.p1[1], &data, sizeof data) == sizeof data);
++      assert(write(context.p2[1], &data, sizeof data) == sizeof data);
++
++      wl_event_loop_dispatch(loop, 0);
++
++      assert(context.count == 1);
++
++      if (context.source1)
++              wl_event_source_remove(context.source1);
++      if (context.source2)
++              wl_event_source_remove(context.source2);
++      wl_event_loop_destroy(loop);
++
++      assert(close(context.p1[0]) == 0);
++      assert(close(context.p1[1]) == 0);
++      assert(close(context.p2[0]) == 0);
++      assert(close(context.p2[1]) == 0);
++}
++
++static int
++signal_callback(int signal_number, void *data)
++{
++      int *got_it = data;
++
++      assert(signal_number == SIGUSR1);
++      ++(*got_it);
++
++      return 1;
++}
++
++TEST(event_loop_signal)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct wl_event_source *source;
++      int got_it = 0;
++
++      source = wl_event_loop_add_signal(loop, SIGUSR1,
++                                        signal_callback, &got_it);
++      assert(source);
++
++      assert(wl_event_loop_dispatch(loop, 0) == 0);
++      assert(!got_it);
++      assert(kill(getpid(), SIGUSR1) == 0);
++      /*
++       * On Linux the signal will be immediately visible in the epoll_wait()
++       * call. However, on FreeBSD we may need a small delay between kill()
++       * call and the signal being visible to the kevent() call. This
++       * sometimes happens when the signal processing and kevent processing
++       * runs on different CPUs, so becomes more likely when the system is
++       * under load (e.g. running all tests in parallel).
++       * See https://github.com/jiixyj/epoll-shim/pull/32
++       * Passing 1ms as the timeout appears to avoid this race condition in
++       * all cases tested so far, but to be safe we use 1000ms which should
++       * be enough time even on a really slow (or emulated) system.
++       */
++      assert(wl_event_loop_dispatch(loop, 1000) == 0);
++      assert(got_it == 1);
++
++      wl_event_source_remove(source);
++      wl_event_loop_destroy(loop);
++}
++
++TEST(event_loop_multiple_same_signals)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct wl_event_source *s1, *s2;
++      int calls_no = 0;
++      int i;
++
++      s1 = wl_event_loop_add_signal(loop, SIGUSR1,
++                                    signal_callback, &calls_no);
++      assert(s1);
++
++      s2 = wl_event_loop_add_signal(loop, SIGUSR1,
++                                    signal_callback, &calls_no);
++      assert(s2);
++
++      assert(wl_event_loop_dispatch(loop, 0) == 0);
++      assert(!calls_no);
++
++      /* Try it more times */
++      for (i = 0; i < 5; ++i) {
++              calls_no = 0;
++              assert(kill(getpid(), SIGUSR1) == 0);
++              /*
++               * We need a non-zero timeout here to allow the test to pass
++               * on non-Linux systems (see comment in event_loop_signal).
++               */
++              assert(wl_event_loop_dispatch(loop, 1000) == 0);
++              assert(calls_no == 2);
++      }
++
++      wl_event_source_remove(s1);
++
++      /* Try it again  with one source */
++      calls_no = 0;
++      assert(kill(getpid(), SIGUSR1) == 0);
++      /*
++       * We need a non-zero timeout here to allow the test to pass
++       * on non-Linux systems (see comment in event_loop_signal).
++       */
++      assert(wl_event_loop_dispatch(loop, 1000) == 0);
++      assert(calls_no == 1);
++
++      wl_event_source_remove(s2);
++
++      wl_event_loop_destroy(loop);
++}
++
++static int
++timer_callback(void *data)
++{
++      int *got_it = data;
++
++      ++(*got_it);
++
++      return 1;
++}
++
++TEST(event_loop_timer)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct wl_event_source *source1, *source2;
++      int got_it = 0;
++
++      source1 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
++      assert(source1);
++      wl_event_source_timer_update(source1, 20);
++
++      source2 = wl_event_loop_add_timer(loop, timer_callback, &got_it);
++      assert(source2);
++      wl_event_source_timer_update(source2, 100);
++
++      /* Check that the timer marked for 20 msec from now fires within 30
++       * msec, and that the timer marked for 100 msec is expected to fire
++       * within an additional 90 msec. (Some extra wait time is provided to
++       * account for reasonable code execution / thread preemption delays.) */
++
++      wl_event_loop_dispatch(loop, 0);
++      assert(got_it == 0);
++      wl_event_loop_dispatch(loop, 30);
++      assert(got_it == 1);
++      wl_event_loop_dispatch(loop, 0);
++      assert(got_it == 1);
++      wl_event_loop_dispatch(loop, 90);
++      assert(got_it == 2);
++
++      wl_event_source_remove(source1);
++      wl_event_source_remove(source2);
++      wl_event_loop_destroy(loop);
++}
++
++#define MSEC_TO_USEC(msec) ((msec) * 1000)
++
++struct timer_update_context {
++      struct wl_event_source *source1, *source2;
++      int count;
++};
++
++static int
++timer_update_callback_1(void *data)
++{
++      struct timer_update_context *context = data;
++
++      context->count++;
++      wl_event_source_timer_update(context->source2, 1000);
++      return 1;
++}
++
++static int
++timer_update_callback_2(void *data)
++{
++      struct timer_update_context *context = data;
++
++      context->count++;
++      wl_event_source_timer_update(context->source1, 1000);
++      return 1;
++}
++
++TEST(event_loop_timer_updates)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct timer_update_context context;
++      struct timeval start_time, end_time, interval;
++
++      /* Create two timers that should expire at the same time (after 10ms).
++       * The first timer to receive its expiry callback updates the other timer
++       * with a much larger timeout (1s). This highlights a bug where
++       * wl_event_source_timer_dispatch would block for this larger timeout
++       * when reading from the timer fd, before calling the second timer's
++       * callback.
++       */
++
++      context.source1 = wl_event_loop_add_timer(loop, timer_update_callback_1,
++                                                &context);
++      assert(context.source1);
++      assert(wl_event_source_timer_update(context.source1, 10) == 0);
++
++      context.source2 = wl_event_loop_add_timer(loop, timer_update_callback_2,
++                                                &context);
++      assert(context.source2);
++      assert(wl_event_source_timer_update(context.source2, 10) == 0);
++
++      context.count = 0;
++
++      /* Since calling the functions between source2's update and
++       * wl_event_loop_dispatch() takes some time, it may happen
++       * that only one timer expires until we call epoll_wait.
++       * This naturally means that only one source is dispatched
++       * and the test fails. To fix that, sleep 15 ms before
++       * calling wl_event_loop_dispatch(). That should be enough
++       * for the second timer to expire.
++       *
++       * https://bugs.freedesktop.org/show_bug.cgi?id=80594
++       */
++      usleep(MSEC_TO_USEC(15));
++
++      gettimeofday(&start_time, NULL);
++      wl_event_loop_dispatch(loop, 20);
++      gettimeofday(&end_time, NULL);
++
++      assert(context.count == 2);
++
++      /* Dispatching the events should not have taken much more than 20ms,
++       * since this is the timeout passed to wl_event_loop_dispatch. If it
++       * blocked, then it will have taken over 1s.
++       * Of course, it could take over 1s anyway on a very slow or heavily
++       * loaded system, so this test isn't 100% perfect.
++       */
++
++      timersub(&end_time, &start_time, &interval);
++      assert(interval.tv_sec < 1);
++
++      wl_event_source_remove(context.source1);
++      wl_event_source_remove(context.source2);
++      wl_event_loop_destroy(loop);
++}
++
++struct timer_order_data {
++      struct wl_event_source *source;
++      int *last_number;
++      int number;
++};
++
++static int
++timer_order_callback(void *data)
++{
++      struct timer_order_data *tod = data;
++
++      /* Check that the timers have the correct sequence */
++      assert(tod->number == *tod->last_number + 2);
++      *tod->last_number = tod->number;
++      return 0;
++}
++
++TEST(event_loop_timer_order)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct timer_order_data order[20];
++      int i, j;
++      int last = -1;
++
++      /* Configure a set of timers so that only timers 1, 3, 5, ..., 19
++       * (in that order) will be dispatched when the event loop is run */
++
++      for (i = 0; i < 20; i++) {
++              order[i].number = i;
++              order[i].last_number = &last;
++              order[i].source =
++                      wl_event_loop_add_timer(loop, timer_order_callback,
++                                              &order[i]);
++              assert(order[i].source);
++              assert(wl_event_source_timer_update(order[i].source, 10) == 0);
++      }
++
++      for (i = 0; i < 20; i++) {
++              /* Permute the order in which timers are updated, so as to
++               * more exhaustively test the underlying priority queue code */
++              j = ((i + 3) * 17) % 20;
++              assert(wl_event_source_timer_update(order[j].source, j) == 0);
++      }
++      for (i = 0; i < 20; i += 2) {
++              assert(wl_event_source_timer_update(order[i].source, 0) == 0);
++      }
++
++      /* Wait until all timers are due */
++      usleep(MSEC_TO_USEC(21));
++      wl_event_loop_dispatch(loop, 0);
++      assert(last == 19);
++
++      for (i = 0; i < 20; i++) {
++              wl_event_source_remove(order[i].source);
++      }
++      wl_event_loop_destroy(loop);
++}
++
++struct timer_cancel_context {
++      struct wl_event_source *timers[4];
++      struct timer_cancel_context *back_refs[4];
++      int order[4];
++      int called, first;
++};
++
++static int
++timer_cancel_callback(void *data) {
++      struct timer_cancel_context **context_ref = data;
++      struct timer_cancel_context *context = *context_ref;
++      int i = (int)(context_ref - context->back_refs);
++
++      context->called++;
++      context->order[i] = context->called;
++
++      if (context->called == 1) {
++              context->first = i;
++              /* Removing a timer always prevents its callback from
++               * being called ... */
++              wl_event_source_remove(context->timers[(i + 1) % 4]);
++              /* ... but disarming or rescheduling a timer does not,
++               * (in the case where the modified timers had already expired
++               * as of when `wl_event_loop_dispatch` was called.) */
++              assert(wl_event_source_timer_update(context->timers[(i + 2) % 4],
++                                                  0) == 0);
++              assert(wl_event_source_timer_update(context->timers[(i + 3) % 4],
++                                                  2000000000) == 0);
++      }
++
++      return 0;
++}
++
++TEST(event_loop_timer_cancellation)
++{
++      struct wl_event_loop *loop = wl_event_loop_create();
++      struct timer_cancel_context context;
++      int i;
++
++      memset(&context, 0, sizeof(context));
++
++      /* Test that when multiple timers are dispatched in a single call
++       * of `wl_event_loop_dispatch`, that having some timers run code
++       * to modify the other timers only actually prevents the other timers
++       * from running their callbacks when the those timers are removed, not
++       * when they are disarmed or rescheduled. */
++
++      for (i = 0; i < 4; i++) {
++              context.back_refs[i] = &context;
++              context.timers[i] =
++                      wl_event_loop_add_timer(loop, timer_cancel_callback,
++                                              &context.back_refs[i]);
++              assert(context.timers[i]);
++
++              assert(wl_event_source_timer_update(context.timers[i], 1) == 0);
++      }
++
++      usleep(MSEC_TO_USEC(2));
++      assert(wl_event_loop_dispatch(loop, 0) == 0);
++
++      /* Tracking which timer was first makes this test independent of the
++       * actual timer dispatch order, which is not guaranteed by the docs */
++      assert(context.order[context.first] == 1);
++      assert(context.order[(context.first + 1) % 4] == 0);
++      assert(context.order[(context.first + 2) % 4] > 1);
++      assert(context.order[(context.first + 3) % 4] > 1);
++
++      wl_event_source_remove(context.timers[context.first]);
++      wl_event_source_remove(context.timers[(context.first + 2) % 4]);
++      wl_event_source_remove(context.timers[(context.first + 3) % 4]);
++
++      wl_event_loop_destroy(loop);
++}
++
++struct event_loop_destroy_listener {
++      struct wl_listener listener;
++      int done;
++};
++
++static void
++event_loop_destroy_notify(struct wl_listener *l, void *data)
++{
++      struct event_loop_destroy_listener *listener =
++              wl_container_of(l, listener, listener);
++
++      listener->done = 1;
++}
++
++TEST(event_loop_destroy)
++{
++      struct wl_event_loop *loop;
++      struct wl_display * display;
++      struct event_loop_destroy_listener a, b;
++
++      loop = wl_event_loop_create();
++      assert(loop);
++
++      a.listener.notify = &event_loop_destroy_notify;
++      a.done = 0;
++      wl_event_loop_add_destroy_listener(loop, &a.listener);
++
++      assert(wl_event_loop_get_destroy_listener(loop,
++             event_loop_destroy_notify) == &a.listener);
++
++      b.listener.notify = &event_loop_destroy_notify;
++      b.done = 0;
++      wl_event_loop_add_destroy_listener(loop, &b.listener);
++
++      wl_list_remove(&a.listener.link);
++      wl_event_loop_destroy(loop);
++
++      assert(!a.done);
++      assert(b.done);
++
++      /* Test to make sure it gets fired on display destruction */
++      display = wl_display_create();
++      assert(display);
++      loop = wl_display_get_event_loop(display);
++      assert(loop);
++
++      a.done = 0;
++      wl_event_loop_add_destroy_listener(loop, &a.listener);
++
++      wl_display_destroy(display);
++
++      assert(a.done);
++}
++
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5f3b3958b9f42a5638dc79d33a03afa140979806
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <errno.h>
++#include <limits.h>
++
++#include "test-runner.h"
++
++static int
++parse_count(const char *str, int *value)
++{
++      char *end;
++      long v;
++
++      errno = 0;
++      v = strtol(str, &end, 10);
++      if ((errno == ERANGE && (v == LONG_MAX || v == LONG_MIN)) ||
++          (errno != 0 && v == 0) ||
++          (end == str) ||
++          (*end != '\0')) {
++              return -1;
++      }
++
++      if (v < 0 || v > INT_MAX) {
++              return -1;
++      }
++
++      *value = v;
++      return 0;
++}
++
++int main(int argc, char *argv[])
++{
++      int expected;
++
++      if (argc != 2)
++              goto help_out;
++
++      if (parse_count(argv[1], &expected) < 0)
++              goto help_out;
++
++      if (count_open_fds() == expected)
++              return EXIT_SUCCESS;
++      else
++              return EXIT_FAILURE;
++
++help_out:
++      fprintf(stderr, "Usage: %s N\n"
++              "where N is the expected number of open file descriptors.\n"
++              "This program exits with a failure if the number "
++              "does not match exactly.\n", argv[0]);
++
++      return EXIT_FAILURE;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..277eccec75f1dd9f63c05c3d41f6e8f6703a1496
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,107 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <string.h>
++#include <time.h>
++#include <assert.h>
++#include "wayland-private.h"
++
++volatile double global_d;
++
++static void
++noop_conversion(void)
++{
++      wl_fixed_t f;
++      union {
++              int64_t i;
++              double d;
++      } u;
++
++      for (f = 0; f < INT32_MAX; f++) {
++              u.i = f;
++              global_d = u.d;
++      }
++}
++
++static void
++magic_conversion(void)
++{
++      wl_fixed_t f;
++
++      for (f = 0; f < INT32_MAX; f++)
++              global_d = wl_fixed_to_double(f);
++}
++
++static void
++mul_conversion(void)
++{
++      wl_fixed_t f;
++
++      /* This will get optimized into multiplication by 1/256 */
++      for (f = 0; f < INT32_MAX; f++)
++              global_d = f / 256.0;
++}
++
++double factor = 256.0;
++
++static void
++div_conversion(void)
++{
++      wl_fixed_t f;
++
++      for (f = 0; f < INT32_MAX; f++)
++              global_d = f / factor;
++}
++
++static void
++benchmark(const char *s, void (*f)(void))
++{
++      struct timespec start, stop, elapsed;
++
++      clock_gettime(CLOCK_MONOTONIC, &start);
++      f();
++      clock_gettime(CLOCK_MONOTONIC, &stop);
++
++      elapsed.tv_sec = stop.tv_sec - start.tv_sec;
++      elapsed.tv_nsec = stop.tv_nsec - start.tv_nsec;
++      if (elapsed.tv_nsec < 0) {
++              elapsed.tv_nsec += 1000000000;
++              elapsed.tv_sec--;
++      }
++      printf("benchmarked %s:\t%ld.%09lds\n",
++             s, elapsed.tv_sec, elapsed.tv_nsec);
++}
++
++int main(void)
++{
++      benchmark("noop", noop_conversion);
++      benchmark("magic", magic_conversion);
++      benchmark("div", div_conversion);
++      benchmark("mul", mul_conversion);
++
++      return 0;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..0b587978ab26eae54fa0aa6dc54b66d897c60cc0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,94 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#define _GNU_SOURCE
++#include <stdlib.h>
++#include <stdio.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(fixed_double_conversions)
++{
++      wl_fixed_t f;
++      double d;
++
++      d = 62.125;
++      f = wl_fixed_from_double(d);
++      fprintf(stderr, "double %lf to fixed %x\n", d, f);
++      assert(f == 0x3e20);
++
++      d = -1200.625;
++      f = wl_fixed_from_double(d);
++      fprintf(stderr, "double %lf to fixed %x\n", d, f);
++      assert(f == -0x4b0a0);
++
++      f = random();
++      d = wl_fixed_to_double(f);
++      fprintf(stderr, "fixed %x to double %lf\n", f, d);
++      assert(d == f / 256.0);
++
++      f = 0x012030;
++      d = wl_fixed_to_double(f);
++      fprintf(stderr, "fixed %x to double %lf\n", f, d);
++      assert(d == 288.1875);
++
++      f = 0x70000000;
++      d = wl_fixed_to_double(f);
++      fprintf(stderr, "fixed %x to double %lf\n", f, d);
++      assert(d == f / 256);
++
++      f = -0x012030;
++      d = wl_fixed_to_double(f);
++      fprintf(stderr, "fixed %x to double %lf\n", f, d);
++      assert(d == -288.1875);
++
++      f = 0x80000000;
++      d = wl_fixed_to_double(f);
++      fprintf(stderr, "fixed %x to double %lf\n", f, d);
++      assert(d == f / 256);
++}
++
++TEST(fixed_int_conversions)
++{
++      wl_fixed_t f;
++      int i;
++
++      i = 62;
++      f = wl_fixed_from_int(i);
++      assert(f == 62 * 256);
++
++      i = -2080;
++      f = wl_fixed_from_int(i);
++      assert(f == -2080 * 256);
++
++      f = 0x277013;
++      i = wl_fixed_to_int(f);
++      assert(i == 0x2770);
++
++      f = -0x5044;
++      i = wl_fixed_to_int(f);
++      assert(i == -0x50);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5c2baf36c1d8c69d49aec33405d87a32f4645497
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,41 @@@
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-protocol-core.h"
++#include "wayland-server-protocol-core.h"
++
++#ifndef WAYLAND_CLIENT_CORE_H
++#error including wayland-client-protocol-core.h did not include wayland-client-core.h!
++#endif
++#ifndef WAYLAND_SERVER_CORE_H
++#error including wayland-server-protocol-core.h did not include wayland-server-core.h!
++#endif
++
++#ifdef WAYLAND_CLIENT_H
++#error including wayland-client-protocol-core.h included wayland-client.h!
++#endif
++#ifdef WAYLAND_SERVER_H
++#error including wayland-server-protocol-core.h included wayland-server.h!
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..87952f7ed335ff24b5e0ee48fcc2f324b9c693df
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,34 @@@
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-protocol.h"
++#include "wayland-server-protocol.h"
++
++#ifndef WAYLAND_CLIENT_H
++#error including wayland-client-protocol.h did not include wayland-client.h!
++#endif
++#ifndef WAYLAND_SERVER_H
++#error including wayland-server-protocol.h did not include wayland-server.h!
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..51856f821e7aac216c6f9eb34f64c636d51c3fdd
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,53 @@@
++/*
++ * Copyright © 2015 Giulio Camuffo
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "wayland-client-core.h"
++#include "wayland-server-core.h"
++
++#ifdef WL_DISPLAY_SYNC
++#error including wayland-client-core.h imported protocol symbols!
++#endif
++#ifdef WL_DISPLAY_ERROR
++#error including wayland-server-core.h imported protocol symbols!
++#endif
++
++#ifdef WAYLAND_CLIENT_H
++#error including wayland-client-core.h included the non-core header!
++#endif
++#ifdef WAYLAND_SERVER_H
++#error including wayland-server-core.h included the non-core header!
++#endif
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++
++#ifndef WL_DISPLAY_SYNC
++#error including wayland-client.h did not import protocol symbols!
++#endif
++#ifndef WL_DISPLAY_ERROR
++#error including wayland-server.h did not import protocol symbols!
++#endif
++
++int main(int argc, char **argv) { return 0; }
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5290bb654ea78bcef3624faffadeef66101abdc3
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,50 @@@
++/*
++ * Copyright © 2016 Yong Bakos
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(interface_equal)
++{
++      const struct wl_interface fake = {
++              "fake", 1, 0, NULL, 0, NULL
++      };
++      const struct wl_interface fake_registry = {
++              "wl_registry", 1, 0, NULL, 0, NULL
++      };
++      const struct wl_interface copy = wl_registry_interface;
++
++      assert(&wl_registry_interface != &copy);
++
++      assert(wl_interface_equal(&wl_registry_interface,
++                                &wl_registry_interface));
++      assert(wl_interface_equal(&wl_registry_interface, &copy));
++      assert(wl_interface_equal(&wl_registry_interface,
++                                &fake_registry));
++      assert(!wl_interface_equal(&wl_registry_interface, &fake));
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..075261817e81c46778557da2c15e7c2cb333e4fa
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,179 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(list_init)
++{
++      struct wl_list list;
++
++      wl_list_init(&list);
++      assert(list.next == &list);
++      assert(list.prev == &list);
++      assert(wl_list_empty(&list));
++}
++
++struct element {
++      int i;
++      struct wl_list link;
++};
++
++TEST(list_insert)
++{
++      struct wl_list list;
++      struct element e;
++
++      wl_list_init(&list);
++      wl_list_insert(&list, &e.link);
++      assert(list.next == &e.link);
++      assert(list.prev == &e.link);
++      assert(e.link.next == &list);
++      assert(e.link.prev == &list);
++}
++
++TEST(list_length)
++{
++      struct wl_list list;
++      struct element e;
++
++      wl_list_init(&list);
++      assert(wl_list_length(&list) == 0);
++      wl_list_insert(&list, &e.link);
++      assert(wl_list_length(&list) == 1);
++      wl_list_remove(&e.link);
++      assert(wl_list_length(&list) == 0);
++}
++
++TEST(list_iterator)
++{
++      struct wl_list list;
++      struct element e1, e2, e3, e4, *e;
++      int reference[] = { 708090, 102030, 5588, 12 };
++      unsigned int i;
++
++      e1.i = 708090;
++      e2.i = 102030;
++      e3.i = 5588;
++      e4.i = 12;
++
++      wl_list_init(&list);
++      wl_list_insert(list.prev, &e1.link);
++      wl_list_insert(list.prev, &e2.link);
++      wl_list_insert(list.prev, &e3.link);
++      wl_list_insert(list.prev, &e4.link);
++
++      i = 0;
++      wl_list_for_each(e, &list, link) {
++              assert(i < ARRAY_LENGTH(reference));
++              assert(e->i == reference[i]);
++              i++;
++      }
++      assert(i == ARRAY_LENGTH(reference));
++
++      i = 0;
++      wl_list_for_each_reverse(e, &list, link) {
++              assert(i < ARRAY_LENGTH(reference));
++              assert(e->i == reference[ARRAY_LENGTH(reference) - i - 1]);
++              i++;
++      }
++      assert(i == ARRAY_LENGTH(reference));
++}
++
++static int
++validate_list(struct wl_list *list, int *reference, int length)
++{
++      struct element *e;
++      int i;
++
++      i = 0;
++      wl_list_for_each(e, list, link) {
++              if (i >= length)
++                      return 0;
++              if (e->i != reference[i])
++                      return 0;
++              i++;
++      }
++
++      if (i != length)
++              return 0;
++
++      return 1;
++}
++
++TEST(list_remove)
++{
++      struct wl_list list;
++      struct element e1, e2, e3;
++      int reference1[] = { 17, 8888, 1000 }, reference2[] = { 17, 1000 };
++
++      e1.i = 17;
++      e2.i = 8888;
++      e3.i = 1000;
++
++      wl_list_init(&list);
++      wl_list_insert(&list, &e1.link);
++      wl_list_insert(list.prev, &e2.link);
++      wl_list_insert(list.prev, &e3.link);
++      assert(validate_list(&list, reference1, ARRAY_LENGTH(reference1)));
++
++      wl_list_remove(&e2.link);
++      assert(validate_list(&list, reference2, ARRAY_LENGTH(reference2)));
++}
++
++TEST(list_insert_list)
++{
++      struct wl_list list, other;
++      struct element e1, e2, e3, e4, e5, e6;
++      int reference1[] = { 17, 8888, 1000 };
++      int reference2[] = { 76543, 1, -500 };
++      int reference3[] = { 17, 76543, 1, -500, 8888, 1000 };
++
++      e1.i = 17;
++      e2.i = 8888;
++      e3.i = 1000;
++
++      wl_list_init(&list);
++      wl_list_insert(&list, &e1.link);
++      wl_list_insert(list.prev, &e2.link);
++      wl_list_insert(list.prev, &e3.link);
++      assert(validate_list(&list, reference1, ARRAY_LENGTH(reference1)));
++
++      e4.i = 76543;
++      e5.i = 1;
++      e6.i = -500;
++
++      wl_list_init(&other);
++      wl_list_insert(&other, &e4.link);
++      wl_list_insert(other.prev, &e5.link);
++      wl_list_insert(other.prev, &e6.link);
++      assert(validate_list(&other, reference2, ARRAY_LENGTH(reference2)));
++
++      wl_list_insert_list(list.next, &other);
++      assert(validate_list(&list, reference3, ARRAY_LENGTH(reference3)));
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..03568ea7acbb76fb8ffb6d4a836c2475171356d8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,137 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include "wayland-private.h"
++#include "test-runner.h"
++
++TEST(map_insert_new)
++{
++      struct wl_map map;
++      uint32_t i, j, k, a, b, c;
++
++      wl_map_init(&map, WL_MAP_SERVER_SIDE);
++      i = wl_map_insert_new(&map, 0, &a);
++      j = wl_map_insert_new(&map, 0, &b);
++      k = wl_map_insert_new(&map, 0, &c);
++      assert(i == WL_SERVER_ID_START);
++      assert(j == WL_SERVER_ID_START + 1);
++      assert(k == WL_SERVER_ID_START + 2);
++
++      assert(wl_map_lookup(&map, i) == &a);
++      assert(wl_map_lookup(&map, j) == &b);
++      assert(wl_map_lookup(&map, k) == &c);
++    wl_map_release(&map);
++
++      wl_map_init(&map, WL_MAP_CLIENT_SIDE);
++      i = wl_map_insert_new(&map, 0, &a);
++      assert(i == 0);
++      assert(wl_map_lookup(&map, i) == &a);
++
++      wl_map_release(&map);
++}
++
++TEST(map_insert_at)
++{
++      struct wl_map map;
++      uint32_t a, b, c;
++
++      wl_map_init(&map, WL_MAP_CLIENT_SIDE);
++      assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START, &a) == 0);
++      assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START + 3, &b) == -1);
++      assert(wl_map_insert_at(&map, 0, WL_SERVER_ID_START + 1, &c) == 0);
++
++      assert(wl_map_lookup(&map, WL_SERVER_ID_START) == &a);
++      assert(wl_map_lookup(&map, WL_SERVER_ID_START + 1) == &c);
++
++      wl_map_release(&map);
++}
++
++TEST(map_remove)
++{
++      struct wl_map map;
++      uint32_t i, j, k, l, a, b, c, d;
++
++      wl_map_init(&map, WL_MAP_SERVER_SIDE);
++      i = wl_map_insert_new(&map, 0, &a);
++      j = wl_map_insert_new(&map, 0, &b);
++      k = wl_map_insert_new(&map, 0, &c);
++      assert(i == WL_SERVER_ID_START);
++      assert(j == WL_SERVER_ID_START + 1);
++      assert(k == WL_SERVER_ID_START + 2);
++
++      assert(wl_map_lookup(&map, i) == &a);
++      assert(wl_map_lookup(&map, j) == &b);
++      assert(wl_map_lookup(&map, k) == &c);
++
++      wl_map_remove(&map, j);
++      assert(wl_map_lookup(&map, j) == NULL);
++
++      /* Verify that we insert d at the hole left by removing b */
++      l = wl_map_insert_new(&map, 0, &d);
++      assert(l == WL_SERVER_ID_START + 1);
++      assert(wl_map_lookup(&map, l) == &d);
++
++      wl_map_release(&map);
++}
++
++TEST(map_flags)
++{
++      struct wl_map map;
++      uint32_t i, j, a, b;
++
++      wl_map_init(&map, WL_MAP_SERVER_SIDE);
++      i = wl_map_insert_new(&map, 0, &a);
++      j = wl_map_insert_new(&map, 1, &b);
++      assert(i == WL_SERVER_ID_START);
++      assert(j == WL_SERVER_ID_START + 1);
++
++      assert(wl_map_lookup(&map, i) == &a);
++      assert(wl_map_lookup(&map, j) == &b);
++
++    assert(wl_map_lookup_flags(&map, i) == 0);
++    assert(wl_map_lookup_flags(&map, j) == 1);
++
++      wl_map_release(&map);
++}
++
++static enum wl_iterator_result never_run(void *element, void *data, uint32_t flags)
++{
++      assert(0);
++}
++
++TEST(map_iter_empty)
++{
++      struct wl_map map;
++
++      wl_map_init(&map, WL_MAP_SERVER_SIDE);
++
++      wl_map_for_each(&map, never_run, NULL);
++
++      wl_map_release(&map);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..5efd6f7aed0d24b1b9f7469fa66444bfd21970e2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,172 @@@
++if not get_option('libraries')
++      error('-Dtests=true requires -Dlibraries=true')
++endif
++
++test_runner = static_library(
++      'test-runner',
++      sources: [
++              'test-runner.c',
++              'test-helpers.c',
++              'test-compositor.c'
++      ],
++      include_directories: [ root_inc, src_inc ],
++      dependencies: [
++              cc.find_library('dl', required: false),
++              dependency('threads'),
++              epoll_dep,
++              ffi_dep,
++              wayland_util_dep,
++              wayland_private_dep,
++              wayland_client_dep,
++              wayland_server_dep
++      ]
++)
++
++test_runner_dep = declare_dependency(
++      link_with: test_runner,
++      include_directories: [ src_inc ],
++      dependencies: [
++              dependency('threads'),
++              cc.find_library('dl', required: false)
++      ]
++)
++
++tests_protocol_xml = files('../protocol/tests.xml')
++
++tests_server_protocol_h = custom_target(
++      'test server protocol header',
++      command: [ wayland_scanner_for_build, '-s', 'server-header', '@INPUT@', '@OUTPUT@' ],
++      input: tests_protocol_xml,
++      output: 'tests-server-protocol.h'
++)
++
++tests_client_protocol_c = custom_target(
++      'test client protocol header',
++      command: [ wayland_scanner_for_build, '-s', 'client-header', '@INPUT@', '@OUTPUT@' ],
++      input: tests_protocol_xml,
++      output: 'tests-client-protocol.h'
++)
++
++tests_protocol_c = custom_target(
++      'test protocol source',
++      command: [ wayland_scanner_for_build, '-s', 'public-code', '@INPUT@', '@OUTPUT@' ],
++      input: tests_protocol_xml,
++      output: 'tests-protocol.c'
++)
++
++benchmark(
++      'fixed-benchmark',
++      executable(
++              'fixed-benchmark',
++              'fixed-benchmark.c',
++              dependencies: [ test_runner_dep, rt_dep ]
++      )
++)
++
++executable(
++      'exec-fd-leak-checker',
++      'exec-fd-leak-checker.c',
++      dependencies: test_runner_dep
++)
++
++if add_languages('cpp', native: false)
++      test(
++              'cpp-compile-test',
++              executable(
++                      'cpp-compile-test',
++                      'cpp-compile-test.cpp',
++                      wayland_server_protocol_h,
++                      include_directories: src_inc
++              )
++      )
++endif
++
++sed_path = find_program('sed').full_path()
++
++if get_option('scanner')
++      test(
++              'scanner-test',
++              find_program('scanner-test.sh'),
++              env: [
++                      'TEST_DATA_DIR=@0@/data'.format(meson.current_source_dir()),
++                      'TEST_OUTPUT_DIR=@0@/output'.format(meson.current_build_dir()),
++                      'SED=@0@'.format(sed_path),
++                      'WAYLAND_SCANNER=@0@'.format(wayland_scanner.full_path()),
++              ],
++      )
++endif
++
++tests = {
++      'array-test': [],
++      'client-test': [ wayland_server_protocol_h ],
++      'display-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++              tests_server_protocol_h,
++              tests_client_protocol_c,
++              tests_protocol_c,
++      ],
++      'connection-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'event-loop-test': [ wayland_server_protocol_h ],
++      'fixed-test': [],
++      'interface-test': [ wayland_client_protocol_h ],
++      'list-test': [],
++      'map-test': [],
++      'sanity-test' : [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'socket-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'queue-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'signal-test': [ wayland_server_protocol_h ],
++      'newsignal-test': [
++              # wayland-server.c is needed here to access wl_priv_* functions
++              files('../src/wayland-server.c'),
++              wayland_server_protocol_h,
++      ],
++      'resources-test': [ wayland_server_protocol_h ],
++      'message-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'compositor-introspection-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'protocol-logger-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++      ],
++      'headers-test': [
++              wayland_client_protocol_h,
++              wayland_server_protocol_h,
++              'headers-protocol-test.c',
++              wayland_client_protocol_core_h,
++              wayland_server_protocol_core_h,
++              'headers-protocol-core-test.c',
++      ],
++      'os-wrappers-test': [],
++}
++
++foreach test_name, test_extra_sources: tests
++      test_sources = [ test_name + '.c' ] + test_extra_sources
++      test_deps = [test_runner_dep, epoll_dep]
++      bin = executable(test_name, test_sources, dependencies: test_deps)
++      test(
++              test_name,
++              bin,
++              env: [
++                      'TEST_SRC_DIR=@0@'.format(meson.current_source_dir()),
++                      'TEST_BUILD_DIR=@0@'.format(meson.current_build_dir()),
++              ],
++      )
++endforeach
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..86f387abcf8ac5f5abd86982c4f8d0c1a170f5c6
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,90 @@@
++/*
++ * Copyright © 2014 Jonas Ådahl
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-private.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++TEST(message_version)
++{
++      unsigned int i;
++      const struct {
++              const struct wl_message *message;
++              int expected_version;
++      } messages[] = {
++              { &wl_pointer_interface.events[WL_POINTER_ENTER], 1 },
++              { &wl_surface_interface.events[WL_SURFACE_ENTER], 1 },
++              { &wl_pointer_interface.methods[WL_POINTER_SET_CURSOR], 1 },
++              { &wl_pointer_interface.methods[WL_POINTER_RELEASE], 3 },
++              { &wl_surface_interface.methods[WL_SURFACE_DESTROY], 1 },
++              { &wl_surface_interface.methods[WL_SURFACE_SET_BUFFER_TRANSFORM], 2 },
++              { &wl_surface_interface.methods[WL_SURFACE_SET_BUFFER_SCALE], 3 },
++      };
++
++      for (i = 0; i < ARRAY_LENGTH(messages); ++i) {
++              assert(wl_message_get_since(messages[i].message) ==
++                     messages[i].expected_version);
++      }
++}
++
++TEST(message_count_arrays)
++{
++      unsigned int i;
++      struct wl_message fake_messages[] = {
++              { "empty", "", NULL },
++              { "non_present", "iufsonh", NULL },
++              { "leading", "aiufsonh", NULL},
++              { "trailing", "iufsonha", NULL },
++              { "middle", "iufasonh", NULL },
++              { "multiple", "aaiufaasonhaa", NULL },
++              { "leading_version", "2aaiufaasonhaa", NULL },
++              { "among_nullables", "iufsa?oa?sah", NULL },
++              { "all_mixed", "2aiufas?oa?sa", NULL },
++      };
++      const struct {
++              const struct wl_message *message;
++              int expected_array_count;
++      } messages[] = {
++              { &wl_pointer_interface.events[WL_POINTER_ENTER], 0 },
++              { &wl_keyboard_interface.events[WL_KEYBOARD_ENTER], 1 },
++              { &fake_messages[0], 0 },
++              { &fake_messages[1], 0 },
++              { &fake_messages[2], 1 },
++              { &fake_messages[3], 1 },
++              { &fake_messages[4], 1 },
++              { &fake_messages[5], 6 },
++              { &fake_messages[6], 6 },
++              { &fake_messages[7], 3 },
++              { &fake_messages[8], 4 },
++      };
++
++      for (i = 0; i < ARRAY_LENGTH(messages); ++i) {
++              assert(wl_message_count_arrays(messages[i].message) ==
++                     messages[i].expected_array_count);
++      }
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..051e10e8b70d213a27272c10b4f1f88bca332e7d
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,337 @@@
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "test-runner.h"
++#include "wayland-server-private.h"
++
++static void
++signal_notify(struct wl_listener *listener, void *data)
++{
++      /* only increase counter*/
++      ++(*((int *) data));
++}
++
++TEST(signal_init)
++{
++      struct wl_priv_signal signal;
++
++      wl_priv_signal_init(&signal);
++
++      /* Test if listeners' list is initialized */
++      assert(&signal.listener_list == signal.listener_list.next
++              && "Maybe wl_priv_signal implementation changed?");
++      assert(signal.listener_list.next == signal.listener_list.prev
++              && "Maybe wl_priv_signal implementation changed?");
++}
++
++TEST(signal_add_get)
++{
++      struct wl_priv_signal signal;
++
++      /* we just need different values of notify */
++      struct wl_listener l1 = {.notify = (wl_notify_func_t) 0x1};
++      struct wl_listener l2 = {.notify = (wl_notify_func_t) 0x2};
++      struct wl_listener l3 = {.notify = (wl_notify_func_t) 0x3};
++      /* one real, why not */
++      struct wl_listener l4 = {.notify = signal_notify};
++
++      wl_priv_signal_init(&signal);
++
++      wl_priv_signal_add(&signal, &l1);
++      wl_priv_signal_add(&signal, &l2);
++      wl_priv_signal_add(&signal, &l3);
++      wl_priv_signal_add(&signal, &l4);
++
++      assert(wl_priv_signal_get(&signal, signal_notify) == &l4);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++
++      /* get should not be destructive */
++      assert(wl_priv_signal_get(&signal, signal_notify) == &l4);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++      assert(wl_priv_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++}
++
++TEST(signal_emit_to_one_listener)
++{
++      int count = 0;
++      int counter;
++
++      struct wl_priv_signal signal;
++      struct wl_listener l1 = {.notify = signal_notify};
++
++      wl_priv_signal_init(&signal);
++      wl_priv_signal_add(&signal, &l1);
++
++      for (counter = 0; counter < 100; counter++)
++              wl_priv_signal_emit(&signal, &count);
++
++      assert(counter == count);
++}
++
++TEST(signal_emit_to_more_listeners)
++{
++      int count = 0;
++      int counter;
++
++      struct wl_priv_signal signal;
++      struct wl_listener l1 = {.notify = signal_notify};
++      struct wl_listener l2 = {.notify = signal_notify};
++      struct wl_listener l3 = {.notify = signal_notify};
++
++      wl_priv_signal_init(&signal);
++      wl_priv_signal_add(&signal, &l1);
++      wl_priv_signal_add(&signal, &l2);
++      wl_priv_signal_add(&signal, &l3);
++
++      for (counter = 0; counter < 100; counter++)
++              wl_priv_signal_emit(&signal, &count);
++
++      assert(3 * counter == count);
++}
++
++struct signal
++{
++      struct wl_priv_signal signal;
++      struct wl_listener l1, l2, l3;
++      int count;
++      struct wl_listener *current;
++};
++
++static void notify_remove(struct wl_listener *l, void *data)
++{
++      struct signal *sig = data;
++      wl_list_remove(&sig->current->link);
++      wl_list_init(&sig->current->link);
++      sig->count++;
++}
++
++#define INIT \
++      wl_priv_signal_init(&signal.signal); \
++      wl_list_init(&signal.l1.link); \
++      wl_list_init(&signal.l2.link); \
++      wl_list_init(&signal.l3.link);
++#define CHECK_EMIT(expected) \
++      signal.count = 0; \
++      wl_priv_signal_emit(&signal.signal, &signal); \
++      assert(signal.count == expected);
++
++TEST(signal_remove_listener)
++{
++      test_set_timeout(4);
++
++      struct signal signal;
++
++      signal.l1.notify = notify_remove;
++      signal.l2.notify = notify_remove;
++      signal.l3.notify = notify_remove;
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++
++      signal.current = &signal.l1;
++      CHECK_EMIT(1)
++      CHECK_EMIT(0)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      CHECK_EMIT(2)
++      CHECK_EMIT(1)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.current = &signal.l2;
++      CHECK_EMIT(1)
++      CHECK_EMIT(1)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++      wl_priv_signal_add(&signal.signal, &signal.l3);
++
++      signal.current = &signal.l1;
++      CHECK_EMIT(3)
++      CHECK_EMIT(2)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++      wl_priv_signal_add(&signal.signal, &signal.l3);
++
++      signal.current = &signal.l2;
++      CHECK_EMIT(2)
++      CHECK_EMIT(2)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++      wl_priv_signal_add(&signal.signal, &signal.l3);
++
++      signal.current = &signal.l3;
++      CHECK_EMIT(2)
++      CHECK_EMIT(2)
++}
++
++static void notify_readd(struct wl_listener *l, void *data)
++{
++      struct signal *signal = data;
++      if (signal->current) {
++              wl_list_remove(&signal->current->link);
++              wl_list_init(&signal->current->link);
++              wl_priv_signal_add(&signal->signal, signal->current);
++      }
++      signal->count++;
++}
++
++static void notify_empty(struct wl_listener *l, void *data)
++{
++      struct signal *signal = data;
++      signal->count++;
++}
++
++TEST(signal_readd_listener)
++{
++      /* Readding a listener is supported, that is it doesn't trigger an
++       * infinite loop or other weird things, but if in a listener you
++       * re-add another listener, that will not be fired in the current
++       * signal emission. */
++
++      test_set_timeout(4);
++
++      struct signal signal;
++
++      signal.l1.notify = notify_readd;
++      signal.l2.notify = notify_readd;
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++
++      signal.current = &signal.l1;
++      CHECK_EMIT(1)
++      CHECK_EMIT(1)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++
++      signal.current = &signal.l2;
++      CHECK_EMIT(1)
++      signal.current = NULL;
++      CHECK_EMIT(2)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.current = &signal.l1;
++      CHECK_EMIT(1)
++      /* l2 was added before l1, so l2 is fired first, which by readding l1
++       * removes it from the current list that is being fired, so 1 is correct */
++      CHECK_EMIT(1)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.l1.notify = notify_empty;
++      signal.current = &signal.l2;
++      CHECK_EMIT(2)
++      CHECK_EMIT(2)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.l1.notify = notify_empty;
++      signal.current = &signal.l1;
++      CHECK_EMIT(2)
++      /* same as before, by readding l1 in the first emit, it now is fired
++       * after l2, so on the second emit it is not fired at all. */
++      CHECK_EMIT(1)
++}
++
++static void notify_addandget(struct wl_listener *l, void *data)
++{
++      struct signal *signal = data;
++      wl_list_remove(&signal->current->link);
++      wl_list_init(&signal->current->link);
++      wl_priv_signal_add(&signal->signal, signal->current);
++
++      assert(wl_priv_signal_get(&signal->signal, signal->current->notify) != NULL);
++
++      signal->count++;
++}
++
++static void notify_get(struct wl_listener *l, void *data)
++{
++      struct signal *signal = data;
++      assert(wl_priv_signal_get(&signal->signal, signal->current->notify) == signal->current);
++      signal->count++;
++}
++
++TEST(signal_get_listener)
++{
++      test_set_timeout(4);
++
++      struct signal signal;
++
++      signal.l1.notify = notify_addandget;
++      signal.l2.notify = notify_get;
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++
++      signal.current = &signal.l2;
++      CHECK_EMIT(1)
++
++      INIT
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.current = &signal.l2;
++      CHECK_EMIT(1)
++
++      INIT
++      signal.l1.notify = notify_get;
++      signal.l2.notify = notify_empty;
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      CHECK_EMIT(2)
++
++      INIT
++      signal.l1.notify = notify_empty;
++      signal.l2.notify = notify_get;
++      wl_priv_signal_add(&signal.signal, &signal.l1);
++      wl_priv_signal_add(&signal.signal, &signal.l2);
++
++      signal.current = &signal.l1;
++      CHECK_EMIT(2)
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8d8c3ab94c486a33e6d7ec1bb9a19c490d297416
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,410 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include "../config.h"
++
++#define _GNU_SOURCE
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <sys/stat.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#include <errno.h>
++#include <stdarg.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <sys/epoll.h>
++
++#include "wayland-private.h"
++#include "test-runner.h"
++#include "wayland-os.h"
++
++static int fall_back;
++
++/* Play nice with sanitizers
++ *
++ * Sanitizers need to intercept syscalls in the compiler run-time library. As
++ * this isn't a separate ELF object, the usual dlsym(RTLD_NEXT) approach won't
++ * work: there can only be one function named "socket" etc. To support this, the
++ * sanitizer library names its interceptors with the prefix __interceptor_ ("__"
++ * being reserved for the implementation) and then weakly aliases it to the real
++ * function. The functions we define below will override the weak alias, and we
++ * can call them by the __interceptor_ name directly. This allows the sanitizer
++ * to do its work before calling the next version of the function via dlsym.
++ *
++ * However! We also don't know which of these functions the sanitizer actually
++ * wants to override, so we have to declare our own weak symbols for
++ * __interceptor_ and check at run time if they linked to anything or not.
++*/
++
++#define DECL(ret_type, func, ...) \
++      ret_type __interceptor_ ## func(__VA_ARGS__) __attribute__((weak)); \
++      static ret_type (*real_ ## func)(__VA_ARGS__);                  \
++      static int wrapped_calls_ ## func;
++
++#define REAL(func) (__interceptor_ ## func) ?                         \
++      __interceptor_ ## func :                                        \
++      (__typeof__(&__interceptor_ ## func))dlsym(RTLD_NEXT, #func)
++
++DECL(int, socket, int, int, int);
++DECL(int, fcntl, int, int, ...);
++DECL(ssize_t, recvmsg, int, struct msghdr *, int);
++DECL(int, epoll_create1, int);
++
++static void
++init_fallbacks(int do_fallbacks)
++{
++      fall_back = do_fallbacks;
++      real_socket = REAL(socket);
++      real_fcntl = REAL(fcntl);
++      real_recvmsg = REAL(recvmsg);
++      real_epoll_create1 = REAL(epoll_create1);
++}
++
++__attribute__ ((visibility("default"))) int
++socket(int domain, int type, int protocol)
++{
++      wrapped_calls_socket++;
++
++      if (fall_back && (type & SOCK_CLOEXEC)) {
++              errno = EINVAL;
++              return -1;
++      }
++
++      return real_socket(domain, type, protocol);
++}
++
++__attribute__ ((visibility("default"))) int
++(fcntl)(int fd, int cmd, ...)
++{
++      va_list ap;
++      int arg;
++      int has_arg;
++
++      wrapped_calls_fcntl++;
++
++      if (fall_back && (cmd == F_DUPFD_CLOEXEC)) {
++              errno = EINVAL;
++              return -1;
++      }
++      switch (cmd) {
++      case F_DUPFD_CLOEXEC:
++      case F_DUPFD:
++      case F_SETFD:
++              va_start(ap, cmd);
++              arg = va_arg(ap, int);
++              has_arg = 1;
++              va_end(ap);
++              break;
++      case F_GETFD:
++              has_arg = 0;
++              break;
++      default:
++              fprintf(stderr, "Unexpected fctnl cmd %d\n", cmd);
++              abort();
++      }
++
++      if (has_arg) {
++              return real_fcntl(fd, cmd, arg);
++      }
++      return real_fcntl(fd, cmd);
++}
++
++__attribute__ ((visibility("default"))) ssize_t
++recvmsg(int sockfd, struct msghdr *msg, int flags)
++{
++      wrapped_calls_recvmsg++;
++
++      if (fall_back && (flags & MSG_CMSG_CLOEXEC)) {
++              errno = EINVAL;
++              return -1;
++      }
++
++      return real_recvmsg(sockfd, msg, flags);
++}
++
++__attribute__ ((visibility("default"))) int
++epoll_create1(int flags)
++{
++      wrapped_calls_epoll_create1++;
++
++      if (fall_back) {
++              wrapped_calls_epoll_create1++; /* epoll_create() not wrapped */
++              errno = EINVAL;
++              return -1;
++      }
++
++      return real_epoll_create1(flags);
++}
++
++static void
++do_os_wrappers_socket_cloexec(int n)
++{
++      int fd;
++      int nr_fds;
++
++      nr_fds = count_open_fds();
++
++      /* simply create a socket that closes on exec */
++      fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++      assert(fd >= 0);
++
++      /*
++       * Must have 2 calls if falling back, but must also allow
++       * falling back without a forced fallback.
++       */
++      assert(wrapped_calls_socket > n);
++
++      exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_socket_cloexec)
++{
++      /* normal case */
++      init_fallbacks(0);
++      do_os_wrappers_socket_cloexec(0);
++}
++
++TEST(os_wrappers_socket_cloexec_fallback)
++{
++      /* forced fallback */
++      init_fallbacks(1);
++      do_os_wrappers_socket_cloexec(1);
++}
++
++static void
++do_os_wrappers_dupfd_cloexec(int n)
++{
++      int base_fd;
++      int fd;
++      int nr_fds;
++
++      nr_fds = count_open_fds();
++
++      base_fd = socket(PF_LOCAL, SOCK_STREAM, 0);
++      assert(base_fd >= 0);
++
++      fd = wl_os_dupfd_cloexec(base_fd, 13);
++      assert(fd >= 13);
++
++      close(base_fd);
++
++      /*
++       * Must have 4 calls if falling back, but must also allow
++       * falling back without a forced fallback.
++       */
++      assert(wrapped_calls_fcntl > n);
++
++      exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_dupfd_cloexec)
++{
++      init_fallbacks(0);
++      do_os_wrappers_dupfd_cloexec(0);
++}
++
++TEST(os_wrappers_dupfd_cloexec_fallback)
++{
++      init_fallbacks(1);
++      do_os_wrappers_dupfd_cloexec(3);
++}
++
++struct marshal_data {
++      struct wl_connection *read_connection;
++      struct wl_connection *write_connection;
++      int s[2];
++      uint32_t read_mask;
++      uint32_t write_mask;
++      union {
++              int h[3];
++      } value;
++      int nr_fds_begin;
++      int nr_fds_conn;
++      int wrapped_calls;
++};
++
++static void
++setup_marshal_data(struct marshal_data *data)
++{
++      assert(socketpair(AF_UNIX,
++                        SOCK_STREAM | SOCK_CLOEXEC, 0, data->s) == 0);
++
++      data->read_connection = wl_connection_create(data->s[0]);
++      assert(data->read_connection);
++
++      data->write_connection = wl_connection_create(data->s[1]);
++      assert(data->write_connection);
++}
++
++static void
++marshal_demarshal(struct marshal_data *data,
++                void (*func)(void), int size, const char *format, ...)
++{
++      struct wl_closure *closure;
++      static const int opcode = 4444;
++      static struct wl_object sender = { NULL, NULL, 1234 };
++      struct wl_message message = { "test", format, NULL };
++      struct wl_map objects;
++      struct wl_object object = { NULL, &func, 1234 };
++      va_list ap;
++      uint32_t msg[1] = { 1234 };
++
++      va_start(ap, format);
++      closure = wl_closure_vmarshal(&sender, opcode, ap, &message);
++      va_end(ap);
++
++      assert(closure);
++      assert(wl_closure_send(closure, data->write_connection) == 0);
++      wl_closure_destroy(closure);
++      assert(wl_connection_flush(data->write_connection) == size);
++
++      assert(wl_connection_read(data->read_connection) == size);
++
++      wl_map_init(&objects, WL_MAP_SERVER_SIDE);
++      object.id = msg[0];
++      closure = wl_connection_demarshal(data->read_connection,
++                                        size, &objects, &message);
++      assert(closure);
++      wl_closure_invoke(closure, WL_CLOSURE_INVOKE_SERVER, &object, 0, data);
++      wl_closure_destroy(closure);
++}
++
++static void
++validate_recvmsg_h(struct marshal_data *data,
++                 struct wl_object *object, int fd1, int fd2, int fd3)
++{
++      struct stat buf1, buf2;
++
++      assert(fd1 >= 0);
++      assert(fd2 >= 0);
++      assert(fd3 >= 0);
++
++      assert(fd1 != data->value.h[0]);
++      assert(fd2 != data->value.h[1]);
++      assert(fd3 != data->value.h[2]);
++
++      assert(fstat(fd3, &buf1) == 0);
++      assert(fstat(data->value.h[2], &buf2) == 0);
++      assert(buf1.st_dev == buf2.st_dev);
++      assert(buf1.st_ino == buf2.st_ino);
++
++      /* close the original file descriptors */
++      close(data->value.h[0]);
++      close(data->value.h[1]);
++      close(data->value.h[2]);
++
++      /* the dup'd (received) fds should still be open */
++      assert(count_open_fds() == data->nr_fds_conn + 3);
++
++      /*
++       * Must have 2 calls if falling back, but must also allow
++       * falling back without a forced fallback.
++       */
++      assert(wrapped_calls_recvmsg > data->wrapped_calls);
++
++      if (data->wrapped_calls == 0 && wrapped_calls_recvmsg > 1)
++              printf("recvmsg fell back unforced.\n");
++
++      /* all fds opened during the test in any way should be gone on exec */
++      exec_fd_leak_check(data->nr_fds_begin);
++}
++
++static void
++do_os_wrappers_recvmsg_cloexec(int n)
++{
++      struct marshal_data data;
++
++      data.nr_fds_begin = count_open_fds();
++#if HAVE_BROKEN_MSG_CMSG_CLOEXEC
++      /* We call the fallback directly on FreeBSD versions with a broken
++       * MSG_CMSG_CLOEXEC, so we don't call the local recvmsg() wrapper. */
++      data.wrapped_calls = 0;
++#else
++      data.wrapped_calls = n;
++#endif
++
++      setup_marshal_data(&data);
++      data.nr_fds_conn = count_open_fds();
++
++      assert(pipe(data.value.h) >= 0);
++
++      data.value.h[2] = open("/dev/zero", O_RDONLY);
++      assert(data.value.h[2] >= 0);
++
++      marshal_demarshal(&data, (void *) validate_recvmsg_h,
++                        8, "hhh", data.value.h[0], data.value.h[1],
++                        data.value.h[2]);
++}
++
++TEST(os_wrappers_recvmsg_cloexec)
++{
++      init_fallbacks(0);
++      do_os_wrappers_recvmsg_cloexec(0);
++}
++
++TEST(os_wrappers_recvmsg_cloexec_fallback)
++{
++      init_fallbacks(1);
++      do_os_wrappers_recvmsg_cloexec(1);
++}
++
++static void
++do_os_wrappers_epoll_create_cloexec(int n)
++{
++      int fd;
++      int nr_fds;
++
++      nr_fds = count_open_fds();
++
++      fd = wl_os_epoll_create_cloexec();
++      assert(fd >= 0);
++
++#ifdef EPOLL_CLOEXEC
++      assert(wrapped_calls_epoll_create1 == n);
++#else
++      printf("No epoll_create1.\n");
++#endif
++
++      exec_fd_leak_check(nr_fds);
++}
++
++TEST(os_wrappers_epoll_create_cloexec)
++{
++      init_fallbacks(0);
++      do_os_wrappers_epoll_create_cloexec(1);
++}
++
++TEST(os_wrappers_epoll_create_cloexec_fallback)
++{
++      init_fallbacks(1);
++      do_os_wrappers_epoll_create_cloexec(2);
++}
++
++/* FIXME: add tests for wl_os_accept_cloexec() */
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..a0ebd22a76d87005be42a98d0fb7e45f89edce01
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,148 @@@
++/*
++ * Copyright © 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++      char *val = getenv("XDG_RUNTIME_DIR");
++      assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++      return val;
++}
++
++struct compositor {
++      struct wl_display *display;
++      struct wl_event_loop *loop;
++      int message;
++      struct wl_client *client;
++};
++
++struct message {
++      enum wl_protocol_logger_type type;
++      const char *class;
++      int opcode;
++      const char *message_name;
++      int args_count;
++} messages[] = {
++      {
++              .type = WL_PROTOCOL_LOGGER_REQUEST,
++              .class = "wl_display",
++              .opcode = 0,
++              .message_name = "sync",
++              .args_count = 1,
++      },
++      {
++              .type = WL_PROTOCOL_LOGGER_EVENT,
++              .class = "wl_callback",
++              .opcode = 0,
++              .message_name = "done",
++              .args_count = 1,
++      },
++      {
++              .type = WL_PROTOCOL_LOGGER_EVENT,
++              .class = "wl_display",
++              .opcode = 1,
++              .message_name = "delete_id",
++              .args_count = 1,
++      },
++};
++
++static void
++logger_func(void *user_data, enum wl_protocol_logger_type type,
++          const struct wl_protocol_logger_message *message)
++{
++      struct compositor *c = user_data;
++      struct message *msg = &messages[c->message++];
++
++      assert(msg->type == type);
++      assert(strcmp(msg->class, wl_resource_get_class(message->resource)) == 0);
++      assert(msg->opcode == message->message_opcode);
++      assert(strcmp(msg->message_name, message->message->name) == 0);
++      assert(msg->args_count == message->arguments_count);
++
++      c->client = wl_resource_get_client(message->resource);
++}
++
++static void
++callback_done(void *data, struct wl_callback *cb, uint32_t time)
++{
++      wl_callback_destroy(cb);
++}
++
++static const struct wl_callback_listener callback_listener = {
++      callback_done,
++};
++
++TEST(logger)
++{
++      test_set_timeout(1);
++
++      const char *socket;
++      struct compositor compositor = { 0 };
++      struct {
++              struct wl_display *display;
++              struct wl_callback *cb;
++      } client;
++      struct wl_protocol_logger *logger;
++
++      require_xdg_runtime_dir();
++
++      compositor.display = wl_display_create();
++      compositor.loop = wl_display_get_event_loop(compositor.display);
++      socket = wl_display_add_socket_auto(compositor.display);
++
++      logger = wl_display_add_protocol_logger(compositor.display,
++                                              logger_func, &compositor);
++
++      client.display = wl_display_connect(socket);
++      client.cb = wl_display_sync(client.display);
++      wl_callback_add_listener(client.cb, &callback_listener, NULL);
++      wl_display_flush(client.display);
++
++      while (compositor.message < 3) {
++              wl_event_loop_dispatch(compositor.loop, -1);
++              wl_display_flush_clients(compositor.display);
++      }
++
++      wl_display_dispatch(client.display);
++      wl_display_disconnect(client.display);
++
++      wl_client_destroy(compositor.client);
++      wl_protocol_logger_destroy(logger);
++      wl_display_destroy(compositor.display);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c09468d7cd70bf9bf88c39bd5bb55e8ee7195f25
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,137 @@@
++/*
++ * Copyright (c) 2019 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <string.h>
++
++#include "wayland-server.h"
++#include "wayland-client.h"
++#include "test-runner.h"
++
++static struct {
++      struct wl_display *display;
++      struct wl_event_loop *loop;
++      int sync_count;
++} server;
++
++static struct {
++      struct wl_display *display;
++      struct wl_callback *callback_a;
++      struct wl_callback *callback_b;
++      int callback_count;
++} client;
++
++static const char *tag_a = "tag";
++static const char *tag_b = "tag";
++
++static void
++callback_done(void *data, struct wl_callback *cb, uint32_t time)
++{
++      const char * const *expected_tag;
++      const char * const *tag;
++
++      if (cb == client.callback_a)
++              expected_tag = &tag_a;
++      else if (cb == client.callback_b)
++              expected_tag = &tag_b;
++      else
++              assert(!"unexpected callback");
++
++      tag = wl_proxy_get_tag((struct wl_proxy *) cb);
++
++      assert(tag == expected_tag);
++      assert(strcmp(*tag, "tag") == 0);
++
++      wl_callback_destroy(cb);
++
++      client.callback_count++;
++}
++
++static const struct wl_callback_listener callback_listener = {
++      callback_done,
++};
++
++static void
++logger_func(void *user_data,
++          enum wl_protocol_logger_type type,
++          const struct wl_protocol_logger_message *message)
++{
++      if (type != WL_PROTOCOL_LOGGER_REQUEST)
++              return;
++
++      assert(strcmp(wl_resource_get_class(message->resource),
++                    "wl_display") == 0);
++      assert(strcmp(message->message->name, "sync") == 0);
++
++      server.sync_count++;
++}
++
++TEST(proxy_tag)
++{
++      const char *socket;
++      struct wl_protocol_logger *logger;
++
++      assert(&tag_a != &tag_b);
++
++      server.display = wl_display_create();
++      assert(server.display);
++      server.loop = wl_display_get_event_loop(server.display);
++      assert(server.loop);
++      socket = wl_display_add_socket_auto(server.display);
++      assert(socket);
++      logger = wl_display_add_protocol_logger(server.display,
++                                              logger_func, NULL);
++      assert(logger);
++
++      client.display = wl_display_connect(socket);
++      assert(client.display);
++
++      client.callback_a = wl_display_sync(client.display);
++      wl_callback_add_listener(client.callback_a, &callback_listener, NULL);
++      wl_proxy_set_tag((struct wl_proxy *) client.callback_a,
++                       &tag_a);
++
++      client.callback_b = wl_display_sync(client.display);
++      wl_callback_add_listener(client.callback_b, &callback_listener, NULL);
++      wl_proxy_set_tag((struct wl_proxy *) client.callback_b,
++                       &tag_b);
++
++      wl_display_flush(client.display);
++
++      while (server.sync_count < 2) {
++              wl_event_loop_dispatch(server.loop, -1);
++              wl_display_flush_clients(server.display);
++      }
++
++      wl_display_dispatch(client.display);
++
++      assert(client.callback_count == 2);
++
++      wl_protocol_logger_destroy(logger);
++      wl_display_disconnect(client.display);
++      wl_event_loop_dispatch(server.loop, 100);
++
++      wl_display_destroy(server.display);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..86a360256fcf07944e61c782889e980672337ed9
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,384 @@@
++/*
++ * Copyright © 2012 Jonas Ådahl
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <stdint.h>
++#include <stdio.h>
++#include <stdbool.h>
++#include <unistd.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <assert.h>
++
++#include "wayland-client.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++#include "test-compositor.h"
++
++#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
++
++static void
++registry_handle_global(void *data, struct wl_registry *registry,
++                     uint32_t id, const char *interface, uint32_t version)
++{
++      int *pcounter = data;
++      (*pcounter)++;
++      assert(*pcounter == 1);
++      wl_registry_destroy(registry);
++}
++
++static const struct wl_registry_listener registry_listener = {
++      registry_handle_global,
++      NULL
++};
++
++/* Test that destroying a proxy object doesn't result in any more
++ * callback being invoked, even though were many queued. */
++static void
++client_test_proxy_destroy(void)
++{
++      struct wl_display *display;
++      struct wl_registry *registry;
++      int counter = 0;
++
++      display = wl_display_connect(NULL);
++      assert(display);
++
++      registry = wl_display_get_registry(display);
++      assert(registry != NULL);
++      wl_registry_add_listener(registry, &registry_listener,
++                               &counter);
++      assert(wl_display_roundtrip(display) != -1);
++
++      assert(counter == 1);
++
++      /* don't destroy the registry, we have already destroyed them
++       * in the global handler */
++      wl_display_disconnect(display);
++}
++
++struct multiple_queues_state {
++      struct wl_display *display;
++      struct wl_callback* callback2;
++      bool done;
++};
++
++static void
++sync_callback(void *data, struct wl_callback *callback, uint32_t serial)
++{
++      struct multiple_queues_state *state = data;
++
++      state->done = true;
++      wl_callback_destroy(callback);
++
++      wl_display_dispatch_pending(state->display);
++
++      wl_callback_destroy(state->callback2);
++}
++
++static const struct wl_callback_listener sync_listener = {
++      sync_callback
++};
++
++/* Test that when receiving the first of two synchronization
++ * callback events, destroying the second one doesn't cause any
++ * errors even if the delete_id event is handled out of order. */
++static void
++client_test_multiple_queues(void)
++{
++      struct wl_event_queue *queue;
++      struct wl_callback *callback1;
++      struct multiple_queues_state state;
++      int ret = 0;
++
++      state.display = wl_display_connect(NULL);
++      assert(state.display);
++
++      queue = wl_display_create_queue(state.display);
++      assert(queue);
++
++      state.done = false;
++      callback1 = wl_display_sync(state.display);
++      assert(callback1 != NULL);
++      wl_callback_add_listener(callback1, &sync_listener, &state);
++      wl_proxy_set_queue((struct wl_proxy *) callback1, queue);
++
++      state.callback2 = wl_display_sync(state.display);
++      assert(state.callback2 != NULL);
++      wl_callback_add_listener(state.callback2, &sync_listener, NULL);
++      wl_proxy_set_queue((struct wl_proxy *) state.callback2, queue);
++
++      wl_display_flush(state.display);
++
++      while (!state.done && !ret)
++              ret = wl_display_dispatch_queue(state.display, queue);
++
++      wl_event_queue_destroy(queue);
++      wl_display_disconnect(state.display);
++
++      exit(ret == -1 ? -1 : 0);
++}
++
++static void
++sync_callback_roundtrip(void *data, struct wl_callback *callback, uint32_t serial)
++{
++      bool *done = data;
++      *done = true;
++}
++
++static const struct wl_callback_listener sync_listener_roundtrip = {
++      sync_callback_roundtrip
++};
++
++/* Test that doing a roundtrip on a queue only the events on that
++ * queue get dispatched. */
++static void
++client_test_queue_roundtrip(void)
++{
++      struct wl_event_queue *queue;
++      struct wl_callback *callback1;
++      struct wl_callback *callback2;
++      struct wl_display *display;
++      bool done1 = false;
++      bool done2 = false;
++
++      display = wl_display_connect(NULL);
++      assert(display);
++
++      queue = wl_display_create_queue(display);
++      assert(queue);
++
++      /* arm a callback on the default queue */
++      callback1 = wl_display_sync(display);
++      assert(callback1 != NULL);
++      wl_callback_add_listener(callback1, &sync_listener_roundtrip, &done1);
++
++      /* arm a callback on the other queue */
++      callback2 = wl_display_sync(display);
++      assert(callback2 != NULL);
++      wl_callback_add_listener(callback2, &sync_listener_roundtrip, &done2);
++      wl_proxy_set_queue((struct wl_proxy *) callback2, queue);
++
++      /* roundtrip on default queue must not dispatch the other queue. */
++      wl_display_roundtrip(display);
++      assert(done1 == true);
++      assert(done2 == false);
++
++      /* re-arm the sync callback on the default queue, so we see that
++       * wl_display_roundtrip_queue() does not dispatch the default queue. */
++      wl_callback_destroy(callback1);
++      done1 = false;
++      callback1 = wl_display_sync(display);
++      assert(callback1 != NULL);
++      wl_callback_add_listener(callback1, &sync_listener_roundtrip, &done1);
++
++      wl_display_roundtrip_queue(display, queue);
++      assert(done1 == false);
++      assert(done2 == true);
++
++      wl_callback_destroy(callback1);
++      wl_callback_destroy(callback2);
++      wl_event_queue_destroy(queue);
++
++      wl_display_disconnect(display);
++}
++
++static void
++client_test_queue_proxy_wrapper(void)
++{
++      struct wl_event_queue *queue;
++      struct wl_display *display;
++      struct wl_display *display_wrapper;
++      struct wl_callback *callback;
++      bool done = false;
++
++      /*
++       * For an illustration of what usage would normally fail without using
++       * proxy wrappers, see the `client_test_queue_set_queue_race' test case.
++       */
++
++      display = wl_display_connect(NULL);
++      assert(display);
++
++      /* Pretend we are in a separate thread where a thread-local queue is
++       * used. */
++      queue = wl_display_create_queue(display);
++      assert(queue);
++
++      display_wrapper = wl_proxy_create_wrapper(display);
++      assert(display_wrapper);
++      wl_proxy_set_queue((struct wl_proxy *) display_wrapper, queue);
++      callback = wl_display_sync(display_wrapper);
++      wl_proxy_wrapper_destroy(display_wrapper);
++      assert(callback != NULL);
++
++      /* Pretend we are now another thread and dispatch the dispatch the main
++       * queue while also knowing our callback is read and queued. */
++      wl_display_roundtrip(display);
++
++      /* Make sure that the pretend-to-be main thread didn't dispatch our
++       * callback, behind our back. */
++      wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
++      wl_display_flush(display);
++
++      assert(!done);
++
++      /* Make sure that we eventually end up dispatching our callback. */
++      while (!done)
++              assert(wl_display_dispatch_queue(display, queue) != -1);
++
++      wl_callback_destroy(callback);
++      wl_event_queue_destroy(queue);
++
++      wl_display_disconnect(display);
++}
++
++static void
++client_test_queue_set_queue_race(void)
++{
++      struct wl_event_queue *queue;
++      struct wl_display *display;
++      struct wl_callback *callback;
++      bool done = false;
++
++      /*
++       * This test illustrates the multi threading scenario which would fail
++       * without doing what is done in the `client_test_queue_proxy_wrapper'
++       * test.
++       */
++
++      display = wl_display_connect(NULL);
++      assert(display);
++
++      /* Pretend we are in a separate thread where a thread-local queue is
++       * used. */
++      queue = wl_display_create_queue(display);
++      assert(queue);
++
++      callback = wl_display_sync(display);
++      assert(callback != NULL);
++
++      /* Pretend we are now another thread and dispatch the dispatch the main
++       * queue while also knowing our callback is read, queued on the wrong
++       * queue, and dispatched. */
++      wl_display_roundtrip(display);
++
++      /* Pretend we are back in the separate thread, and continue with setting
++       * up our callback. */
++      wl_callback_add_listener(callback, &sync_listener_roundtrip, &done);
++      wl_proxy_set_queue((struct wl_proxy *) callback, queue);
++
++      /* Roundtrip our separate thread queue to make sure any events are
++       * dispatched. */
++      wl_display_roundtrip_queue(display, queue);
++
++      /* Verify that the callback has indeed been dropped. */
++      assert(!done);
++
++      wl_callback_destroy(callback);
++      wl_event_queue_destroy(queue);
++
++      wl_display_disconnect(display);
++}
++
++static void
++dummy_bind(struct wl_client *client,
++         void *data, uint32_t version, uint32_t id)
++{
++}
++
++TEST(queue_proxy_destroy)
++{
++      struct display *d;
++      const struct wl_interface *dummy_interfaces[] = {
++              &wl_seat_interface,
++              &wl_pointer_interface,
++              &wl_keyboard_interface,
++              &wl_surface_interface
++      };
++      unsigned int i;
++
++      d = display_create();
++
++      for (i = 0; i < ARRAY_LENGTH(dummy_interfaces); i++)
++              wl_global_create(d->wl_display, dummy_interfaces[i],
++                               dummy_interfaces[i]->version,
++                               NULL, dummy_bind);
++
++      test_set_timeout(2);
++
++      client_create_noarg(d, client_test_proxy_destroy);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++TEST(queue_multiple_queues)
++{
++      struct display *d = display_create();
++
++      test_set_timeout(2);
++
++      client_create_noarg(d, client_test_multiple_queues);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++TEST(queue_roundtrip)
++{
++      struct display *d = display_create();
++
++      test_set_timeout(2);
++
++      client_create_noarg(d, client_test_queue_roundtrip);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++TEST(queue_set_queue_proxy_wrapper)
++{
++      struct display *d = display_create();
++
++      test_set_timeout(2);
++
++      client_create_noarg(d, client_test_queue_proxy_wrapper);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++TEST(queue_set_queue_race)
++{
++      struct display *d = display_create();
++
++      test_set_timeout(2);
++
++      client_create_noarg(d, client_test_queue_set_queue_race);
++      display_run(d);
++
++      display_destroy(d);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..fa6ba2b259b6a664fcf818e97ccf34a082978cd0
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,208 @@@
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <sys/socket.h>
++#include <unistd.h>
++#include <stdint.h>
++
++#include "wayland-server.h"
++#include "test-runner.h"
++
++TEST(create_resource_tst)
++{
++      struct wl_display *display;
++      struct wl_client *client;
++      struct wl_resource *res;
++      struct wl_list *link;
++      int s[2];
++      uint32_t id;
++
++      assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++      display = wl_display_create();
++      assert(display);
++      client = wl_client_create(display, s[0]);
++      assert(client);
++
++      res = wl_resource_create(client, &wl_seat_interface, 4, 0);
++      assert(res);
++
++      /* setters/getters */
++      assert(wl_resource_get_version(res) == 4);
++
++      assert(client == wl_resource_get_client(res));
++      id = wl_resource_get_id(res);
++      assert(wl_client_get_object(client, id) == res);
++
++      link = wl_resource_get_link(res);
++      assert(link);
++      assert(wl_resource_from_link(link) == res);
++
++      wl_resource_set_user_data(res, (void *) 0xbee);
++      assert(wl_resource_get_user_data(res) == (void *) 0xbee);
++
++      wl_resource_destroy(res);
++      wl_client_destroy(client);
++      wl_display_destroy(display);
++      close(s[1]);
++}
++
++static void
++res_destroy_func(struct wl_resource *res)
++{
++      assert(res);
++
++      _Bool *destr = wl_resource_get_user_data(res);
++      *destr = 1;
++}
++
++static _Bool notify_called = 0;
++static void
++destroy_notify(struct wl_listener *l, void *data)
++{
++      assert(l && data);
++      notify_called = 1;
++
++      /* In real code it's common to free the structure holding the
++       * listener at this point, but not to remove it from the list.
++       *
++       * That's fine since this is a destruction notification and
++       * it's the last time this signal can fire.  We set these
++       * to NULL so we can check them later to ensure no write after
++       * "free" occurred.
++       */
++      l->link.prev = NULL;
++      l->link.next = NULL;
++}
++
++TEST(destroy_res_tst)
++{
++      struct wl_display *display;
++      struct wl_client *client;
++      struct wl_resource *res;
++      int s[2];
++      unsigned id;
++      struct wl_list *link;
++
++      _Bool destroyed = 0;
++      struct wl_listener destroy_listener = {
++              .notify = &destroy_notify
++      };
++
++      assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++      display = wl_display_create();
++      assert(display);
++      client = wl_client_create(display, s[0]);
++      assert(client);
++
++      res = wl_resource_create(client, &wl_seat_interface, 4, 0);
++      assert(res);
++      wl_resource_set_implementation(res, NULL, &destroyed, res_destroy_func);
++      wl_resource_add_destroy_listener(res, &destroy_listener);
++
++      id = wl_resource_get_id(res);
++      link = wl_resource_get_link(res);
++      assert(link);
++
++      wl_resource_destroy(res);
++      assert(destroyed);
++      assert(notify_called); /* check if signal was emitted */
++      assert(wl_client_get_object(client, id) == NULL);
++      assert(destroy_listener.link.prev == NULL);
++      assert(destroy_listener.link.next == NULL);
++
++      res = wl_resource_create(client, &wl_seat_interface, 2, 0);
++      assert(res);
++      destroyed = 0;
++      notify_called = 0;
++      wl_resource_set_destructor(res, res_destroy_func);
++      wl_resource_set_user_data(res, &destroyed);
++      wl_resource_add_destroy_listener(res, &destroy_listener);
++      /* client should destroy the resource upon its destruction */
++      wl_client_destroy(client);
++      assert(destroyed);
++      assert(notify_called);
++      assert(destroy_listener.link.prev == NULL);
++      assert(destroy_listener.link.next == NULL);
++
++      wl_display_destroy(display);
++      close(s[1]);
++}
++
++TEST(create_resource_with_same_id)
++{
++      struct wl_display *display;
++      struct wl_client *client;
++      struct wl_resource *res, *res2;
++      int s[2];
++      uint32_t id;
++
++      assert(socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, s) == 0);
++      display = wl_display_create();
++      assert(display);
++      client = wl_client_create(display, s[0]);
++      assert(client);
++
++      res = wl_resource_create(client, &wl_seat_interface, 2, 0);
++      assert(res);
++      id = wl_resource_get_id(res);
++      assert(wl_client_get_object(client, id) == res);
++
++      /* this one should replace the old one */
++      res2 = wl_resource_create(client, &wl_seat_interface, 1, id);
++      assert(res2 != NULL);
++      assert(wl_client_get_object(client, id) == res2);
++
++      wl_resource_destroy(res2);
++      wl_resource_destroy(res);
++
++      wl_client_destroy(client);
++      wl_display_destroy(display);
++      close(s[1]);
++}
++
++static void
++display_destroy_notify(struct wl_listener *l, void *data)
++{
++      l->link.prev = l->link.next = NULL;
++}
++
++TEST(free_without_remove)
++{
++      struct wl_display *display;
++      struct wl_listener a, b;
++
++      display = wl_display_create();
++      a.notify = display_destroy_notify;
++      b.notify = display_destroy_notify;
++
++      wl_display_add_destroy_listener(display, &a);
++      wl_display_add_destroy_listener(display, &b);
++
++      wl_display_destroy(display);
++
++      assert(a.link.next == a.link.prev && a.link.next == NULL);
++      assert(b.link.next == b.link.prev && b.link.next == NULL);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..1a33c12799e53b181385e13325f7bc226af056f8
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,250 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <unistd.h>
++
++#include "test-runner.h"
++#include "wayland-util.h"
++#include "wayland-private.h"
++
++#include "test-compositor.h"
++
++extern int fd_leak_check_enabled;
++
++TEST(empty)
++{
++}
++
++TEST(exit_success)
++{
++      exit(EXIT_SUCCESS);
++}
++
++FAIL_TEST(exit_failure)
++{
++      exit(EXIT_FAILURE);
++}
++
++FAIL_TEST(fail_abort)
++{
++      test_disable_coredumps();
++      abort();
++}
++
++FAIL_TEST(fail_wl_abort)
++{
++      test_disable_coredumps();
++      wl_abort("Abort the program\n");
++}
++
++FAIL_TEST(fail_kill)
++{
++      kill(getpid(), SIGTERM);
++}
++
++FAIL_TEST(fail_segv)
++{
++      char * volatile *null = 0;
++
++      test_disable_coredumps();
++      *null = "Goodbye, world";
++}
++
++FAIL_TEST(sanity_assert)
++{
++      test_disable_coredumps();
++      /* must fail */
++      assert(0);
++}
++
++FAIL_TEST(sanity_fd_leak)
++{
++      int fd[2];
++
++      assert(fd_leak_check_enabled);
++
++      /* leak 2 file descriptors */
++      if (pipe(fd) < 0)
++              exit(EXIT_SUCCESS); /* failed to fail */
++
++      test_disable_coredumps();
++}
++
++FAIL_TEST(sanity_fd_leak_exec)
++{
++      int fd[2];
++      int nr_fds = count_open_fds();
++
++      /* leak 2 file descriptors */
++      if (pipe(fd) < 0)
++              exit(EXIT_SUCCESS); /* failed to fail */
++
++      test_disable_coredumps();
++      exec_fd_leak_check(nr_fds);
++}
++
++TEST(sanity_fd_exec)
++{
++      int fd[2];
++      int nr_fds = count_open_fds();
++
++      /* create 2 file descriptors, that should pass over exec */
++      assert(pipe(fd) >= 0);
++
++      exec_fd_leak_check(nr_fds + 2);
++}
++
++static void
++sanity_fd_no_leak(void)
++{
++      int fd[2];
++
++      assert(fd_leak_check_enabled);
++
++      /* leak 2 file descriptors */
++      if (pipe(fd) < 0)
++              exit(EXIT_SUCCESS); /* failed to fail */
++
++      close(fd[0]);
++      close(fd[1]);
++}
++
++static void
++sanity_client_no_leak(void)
++{
++      struct wl_display *display = wl_display_connect(NULL);
++      assert(display);
++
++      wl_display_disconnect(display);
++}
++
++TEST(tc_client_no_fd_leaks)
++{
++      struct display *d = display_create();
++
++      /* Client which does not consume the WAYLAND_DISPLAY socket. */
++      client_create_noarg(d, sanity_fd_no_leak);
++      display_run(d);
++
++      /* Client which does consume the WAYLAND_DISPLAY socket. */
++      client_create_noarg(d, sanity_client_no_leak);
++      display_run(d);
++
++      display_destroy(d);
++}
++
++FAIL_TEST(tc_client_fd_leaks)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, sanity_fd_leak);
++      display_run(d);
++
++      test_disable_coredumps();
++      display_destroy(d);
++}
++
++FAIL_TEST(tc_client_fd_leaks_exec)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, sanity_fd_leak_exec);
++      display_run(d);
++
++      test_disable_coredumps();
++      display_destroy(d);
++}
++
++FAIL_TEST(timeout_tst)
++{
++      test_set_timeout(1);
++      test_disable_coredumps();
++      /* test should reach timeout */
++      test_sleep(2);
++}
++
++TEST(timeout2_tst)
++{
++      /* the test should end before reaching timeout,
++       * thus it should pass */
++      test_set_timeout(1);
++      /* 200 000 microsec = 0.2 sec */
++      test_usleep(200000);
++}
++
++FAIL_TEST(timeout_reset_tst)
++{
++      test_set_timeout(5);
++      test_set_timeout(10);
++      test_set_timeout(1);
++
++      test_disable_coredumps();
++      /* test should fail on timeout */
++      test_sleep(2);
++}
++
++TEST(timeout_turnoff)
++{
++      test_set_timeout(1);
++      test_set_timeout(0);
++
++      test_usleep(2);
++}
++
++/* test timeouts with test-compositor */
++FAIL_TEST(tc_timeout_tst)
++{
++      struct display *d = display_create();
++      client_create_noarg(d, timeout_tst);
++      display_run(d);
++      test_disable_coredumps();
++      display_destroy(d);
++}
++
++FAIL_TEST(tc_timeout2_tst)
++{
++      struct display *d = display_create();
++      client_create_noarg(d, timeout_reset_tst);
++      display_run(d);
++      test_disable_coredumps();
++      display_destroy(d);
++}
++
++TEST(tc_timeout3_tst)
++{
++      struct display *d = display_create();
++
++      client_create_noarg(d, timeout2_tst);
++      display_run(d);
++
++      client_create_noarg(d, timeout_turnoff);
++      display_run(d);
++
++      display_destroy(d);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..35ba0473d0307a5e608354fe4384d5fd37d58f61
new file mode 100755 (executable)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,78 @@@
++#!/bin/sh
++
++echo "srcdir: $srcdir"
++echo "scanner: $WAYLAND_SCANNER"
++echo "test_data_dir: $TEST_DATA_DIR"
++echo "test_output_dir: $TEST_OUTPUT_DIR"
++echo "pwd: $PWD"
++echo "sed: $SED"
++
++RETCODE=0
++
++hard_fail() {
++      echo "$@" "ERROR"
++      exit 99
++}
++
++fail() {
++      echo "$@" "FAIL"
++      RETCODE=1
++}
++
++mkdir -p "$TEST_OUTPUT_DIR" || hard_fail "setup"
++
++generate_and_compare() {
++      echo
++      echo "Testing $1 generation: $2 -> $3"
++
++      "$WAYLAND_SCANNER" $1 < "$TEST_DATA_DIR/$2" > "$TEST_OUTPUT_DIR/$3" || \
++              hard_fail "$2 -> $3"
++
++      "$SED" -i -e 's/Generated by wayland-scanner [0-9.]*/SCANNER TEST/' \
++              "$TEST_OUTPUT_DIR/$3" || hard_fail "$2 -> $3"
++
++      diff -q "$TEST_DATA_DIR/$3" "$TEST_OUTPUT_DIR/$3" && \
++              echo "$2 -> $3 PASS" || \
++              fail "$2 -> $3"
++}
++
++verify_error() {
++      echo
++      echo "Checking that reading $1 gives an error on line $3"
++
++      [ -f "$TEST_DATA_DIR/$1" ] || hard_fail "$1 not present"
++
++      # Confirm failure error code
++      "$WAYLAND_SCANNER" server-header < "$TEST_DATA_DIR/$1" >/dev/null 2>"$TEST_OUTPUT_DIR/$2" && \
++              fail "$1 return code check"
++
++      # Verify that an error is produced at the correct line
++      grep -q "<stdin>:$3: error:" "$TEST_OUTPUT_DIR/$2" && echo "$1 PASS" || fail "$1 line number check"
++}
++
++generate_and_compare "code" "example.xml" "example-code.c"
++generate_and_compare "client-header" "example.xml" "example-client.h"
++generate_and_compare "server-header" "example.xml" "example-server.h"
++
++generate_and_compare "code" "small.xml" "small-code.c"
++generate_and_compare "client-header" "small.xml" "small-client.h"
++generate_and_compare "server-header" "small.xml" "small-server.h"
++
++generate_and_compare "-c code" "small.xml" "small-code-core.c"
++generate_and_compare "-c client-header" "small.xml" "small-client-core.h"
++generate_and_compare "-c server-header" "small.xml" "small-server-core.h"
++
++# The existing "code" must produce result identical to "public-code"
++generate_and_compare "code" "small.xml" "small-code.c"
++generate_and_compare "public-code" "small.xml" "small-code.c"
++generate_and_compare "private-code" "small.xml" "small-private-code.c"
++
++verify_error "bad-identifier-arg.xml" "bad-identifier-arg.log" 7
++verify_error "bad-identifier-entry.xml" "bad-identifier-entry.log" 8
++verify_error "bad-identifier-enum.xml" "bad-identifier-enum.log" 6
++verify_error "bad-identifier-event.xml" "bad-identifier-event.log" 6
++verify_error "bad-identifier-interface.xml" "bad-identifier-interface.log" 3
++verify_error "bad-identifier-protocol.xml" "bad-identifier-protocol.log" 2
++verify_error "bad-identifier-request.xml" "bad-identifier-request.log" 6
++
++exit $RETCODE
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..f7e1bd6fe1aad99774756932b28db2a464e1b228
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,158 @@@
++/*
++ * Copyright © 2013 Marek Chalupa
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++
++#include "wayland-server.h"
++#include "test-runner.h"
++
++static void
++signal_notify(struct wl_listener *listener, void *data)
++{
++      /* only increase counter*/
++      ++(*((int *) data));
++}
++
++TEST(signal_init)
++{
++      struct wl_signal signal;
++
++      wl_signal_init(&signal);
++
++      /* Test if listeners' list is initialized */
++      assert(&signal.listener_list == signal.listener_list.next
++              && "Maybe wl_signal implementation changed?");
++      assert(signal.listener_list.next == signal.listener_list.prev
++              && "Maybe wl_signal implementation changed?");
++}
++
++TEST(signal_add_get)
++{
++      struct wl_signal signal;
++
++      /* we just need different values of notify */
++      struct wl_listener l1 = {.notify = (wl_notify_func_t) 0x1};
++      struct wl_listener l2 = {.notify = (wl_notify_func_t) 0x2};
++      struct wl_listener l3 = {.notify = (wl_notify_func_t) 0x3};
++      /* one real, why not */
++      struct wl_listener l4 = {.notify = signal_notify};
++
++      wl_signal_init(&signal);
++
++      wl_signal_add(&signal, &l1);
++      wl_signal_add(&signal, &l2);
++      wl_signal_add(&signal, &l3);
++      wl_signal_add(&signal, &l4);
++
++      assert(wl_signal_get(&signal, signal_notify) == &l4);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++
++      /* get should not be destructive */
++      assert(wl_signal_get(&signal, signal_notify) == &l4);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x3) == &l3);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x2) == &l2);
++      assert(wl_signal_get(&signal, (wl_notify_func_t) 0x1) == &l1);
++}
++
++TEST(signal_emit_to_one_listener)
++{
++      int count = 0;
++      int counter;
++
++      struct wl_signal signal;
++      struct wl_listener l1 = {.notify = signal_notify};
++
++      wl_signal_init(&signal);
++      wl_signal_add(&signal, &l1);
++
++      for (counter = 0; counter < 100; counter++)
++              wl_signal_emit(&signal, &count);
++
++      assert(counter == count);
++}
++
++TEST(signal_emit_to_more_listeners)
++{
++      int count = 0;
++      int counter;
++
++      struct wl_signal signal;
++      struct wl_listener l1 = {.notify = signal_notify};
++      struct wl_listener l2 = {.notify = signal_notify};
++      struct wl_listener l3 = {.notify = signal_notify};
++
++      wl_signal_init(&signal);
++      wl_signal_add(&signal, &l1);
++      wl_signal_add(&signal, &l2);
++      wl_signal_add(&signal, &l3);
++
++      for (counter = 0; counter < 100; counter++)
++              wl_signal_emit(&signal, &count);
++
++      assert(3 * counter == count);
++}
++
++struct signal_emit_mutable_data {
++      int count;
++      struct wl_listener *remove_listener;
++};
++
++static void
++signal_notify_mutable(struct wl_listener *listener, void *data)
++{
++      struct signal_emit_mutable_data *test_data = data;
++      test_data->count++;
++}
++
++static void
++signal_notify_and_remove_mutable(struct wl_listener *listener, void *data)
++{
++      struct signal_emit_mutable_data *test_data = data;
++      signal_notify_mutable(listener, test_data);
++      wl_list_remove(&test_data->remove_listener->link);
++}
++
++TEST(signal_emit_mutable)
++{
++      struct signal_emit_mutable_data data = {0};
++
++      /* l2 will remove l3 before l3 is notified */
++      struct wl_signal signal;
++      struct wl_listener l1 = {.notify = signal_notify_mutable};
++      struct wl_listener l2 = {.notify = signal_notify_and_remove_mutable};
++      struct wl_listener l3 = {.notify = signal_notify_mutable};
++
++      wl_signal_init(&signal);
++      wl_signal_add(&signal, &l1);
++      wl_signal_add(&signal, &l2);
++      wl_signal_add(&signal, &l3);
++
++      data.remove_listener = &l3;
++      wl_signal_emit_mutable(&signal, &data);
++
++      assert(data.count == 2);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..78743dc3a20f24cf04b2cc3bf859db8f6d309b13
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,289 @@@
++/*
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdlib.h>
++#include <assert.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <sys/socket.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/un.h>
++#include <unistd.h>
++
++#include "wayland-client.h"
++#include "wayland-os.h"
++#include "wayland-server.h"
++#include "test-runner.h"
++
++/* Paths longer than what the .sun_path array can contain must be rejected.
++ * This is a hard limitation of assigning a name to AF_UNIX/AF_LOCAL sockets.
++ * See `man 7 unix`.
++ */
++
++static struct sockaddr_un example_sockaddr_un;
++
++#define TOO_LONG (1 + sizeof example_sockaddr_un.sun_path)
++
++/* Ensure the connection doesn't fail due to lack of XDG_RUNTIME_DIR. */
++static const char *
++require_xdg_runtime_dir(void)
++{
++      char *val = getenv("XDG_RUNTIME_DIR");
++      assert(val && val[0] == '/' && "set $XDG_RUNTIME_DIR to run this test");
++
++      return val;
++}
++
++TEST(socket_path_overflow_client_connect)
++{
++      char path[TOO_LONG];
++      struct wl_display *d;
++
++      require_xdg_runtime_dir();
++
++      memset(path, 'a', sizeof path);
++      path[sizeof path - 1] = '\0';
++
++      d = wl_display_connect(path);
++      assert(d == NULL);
++      assert(errno == ENAMETOOLONG);
++
++      /* This is useless, but prevents a warning about example_sockaddr_un
++       * being discarded from the compilation unit. */
++      strcpy(example_sockaddr_un.sun_path, "happy now clang?");
++      assert(example_sockaddr_un.sun_path[0] != '\0');
++}
++
++TEST(socket_path_overflow_server_create)
++{
++      char path[TOO_LONG];
++      struct wl_display *d;
++      int ret;
++
++      require_xdg_runtime_dir();
++
++      memset(path, 'a', sizeof path);
++      path[sizeof path - 1] = '\0';
++
++      d = wl_display_create();
++      assert(d != NULL);
++
++      ret = wl_display_add_socket(d, path);
++      assert(ret < 0);
++      assert(errno == ENAMETOOLONG);
++
++      wl_display_destroy(d);
++}
++
++TEST(add_existing_socket)
++{
++      char path[sizeof example_sockaddr_un.sun_path];
++      const char *name = "wayland-test-0";
++      const char *xdg_runtime_dir;
++      struct wl_display *d;
++      int ret;
++      size_t len;
++
++      xdg_runtime_dir = require_xdg_runtime_dir();
++
++      d = wl_display_create();
++      assert(d != NULL);
++
++      /* this one should be OK */
++      ret = wl_display_add_socket(d, name);
++      assert(ret == 0);
++
++      /* this one should fail */
++      ret = wl_display_add_socket(d, name);
++      assert(ret < 0);
++
++      /* the original socket should still exist.
++       * this was a bug introduced in e2c0d47b0c77f18cd90e9c6eabb358c4d89681c8 */
++      len = snprintf(path, sizeof example_sockaddr_un.sun_path, "%s/%s",
++                     xdg_runtime_dir, name);
++      assert(len < sizeof example_sockaddr_un.sun_path
++             && "Bug in test. Path too long");
++
++      assert(access(path, F_OK) != -1);
++
++      /* the original socket should still exist */
++      ret = wl_display_add_socket(d, name);
++      assert(ret < 0);
++
++      wl_display_destroy(d);
++}
++
++TEST(add_socket_auto)
++{
++      /* the number of auto sockets is currently 32,
++       * set in wayland-server.c.
++       */
++      const int MAX_SOCKETS = 32;
++
++      char path[sizeof example_sockaddr_un.sun_path];
++      const char *name;
++      const char *xdg_runtime_dir;
++      struct wl_display *d;
++      int i;
++      size_t len;
++
++      xdg_runtime_dir = require_xdg_runtime_dir();
++
++      d = wl_display_create();
++      assert(d != NULL);
++
++      for (i = 0; i <= MAX_SOCKETS; ++i) {
++              name = wl_display_add_socket_auto(d);
++              assert(name != NULL);
++
++              len = snprintf(path, sizeof example_sockaddr_un.sun_path,
++                             "%s/%s", xdg_runtime_dir, name);
++              assert(len < sizeof example_sockaddr_un.sun_path
++                     && "Bug in test. Path too long");
++
++              /* was the socket created correctly? */
++              assert(access(path, F_OK) != -1);
++
++              /* is the name sequential? */
++              len = snprintf(path, sizeof example_sockaddr_un.sun_path,
++                             "wayland-%d", i);
++              assert(strcmp(name, path) == 0);
++      }
++
++      /* next addition should return NULL */
++      name = wl_display_add_socket_auto(d);
++      assert(name == NULL);
++
++      /* check if the socket was not deleted the last time */
++      name = wl_display_add_socket_auto(d);
++      assert(name == NULL);
++
++      wl_display_destroy(d);
++}
++
++struct client_create_listener {
++      struct wl_listener listener;
++      struct wl_display *display;
++};
++
++struct client_destroy_listener {
++      struct wl_listener listener;
++      struct wl_display *display;
++};
++
++static void
++client_destroy_notify(struct wl_listener *l, void *data)
++{
++      struct client_destroy_listener *listener =
++              wl_container_of(l, listener, listener);
++      wl_display_terminate(listener->display);
++      free(listener);
++}
++
++static void
++client_create_notify(struct wl_listener *l, void *data)
++{
++      struct wl_client *client = data;
++      struct client_create_listener *listener =
++              wl_container_of(l, listener, listener);
++      struct client_destroy_listener *destroy_listener = (struct client_destroy_listener *)malloc(sizeof *destroy_listener);
++      assert(destroy_listener != NULL);
++      destroy_listener->display = listener->display;
++      destroy_listener->listener.notify = client_destroy_notify;
++      wl_client_add_destroy_listener(client, &destroy_listener->listener);
++}
++
++TEST(absolute_socket_path)
++{
++      struct wl_display *display;
++      struct client_create_listener client_create_listener;
++      struct sockaddr_un addr;
++      int fd;
++      socklen_t size;
++      const char *xdg_runtime_dir;
++      size_t len;
++      int ret;
++      pid_t pid;
++
++      /* It's a little weird that this test about absolute socket paths
++       * uses XDG_RUNTIME_DIR, but that's the only location guaranteed
++       * by test-runner to be both writable and unique. This isn't
++       * really a problem; we'll just take care that the leaf-level
++       * filename used for the socket isn't anything that would
++       * accidentally be generated by a default usage of wl_display_connect(). */
++      xdg_runtime_dir = require_xdg_runtime_dir();
++      memset(&addr, 0, sizeof addr);
++      len = snprintf(addr.sun_path, sizeof addr.sun_path,
++                     "%s/%s", xdg_runtime_dir, "wayland-absolute-0");
++      assert(len < sizeof addr.sun_path
++             && "Bug in test. Path too long");
++
++      /* The path must not exist prior to binding. */
++      assert(access(addr.sun_path, F_OK) == -1);
++
++      size = offsetof (struct sockaddr_un, sun_path) + strlen(addr.sun_path);
++      addr.sun_family = AF_LOCAL;
++      fd = wl_os_socket_cloexec(PF_LOCAL, SOCK_STREAM, 0);
++      assert(fd >= 0 );
++      ret = bind(fd, (struct sockaddr *) &addr, size);
++      assert(ret >= 0);
++      ret = listen(fd, 128);
++      assert(ret >= 0);
++
++      /* Start server display. Be careful (by avoiding wl_display_add_socket_auto()
++       * to offer only the absolutely qualified socket made above. */
++      display = wl_display_create();
++      assert(display != NULL);
++      client_create_listener.listener.notify = client_create_notify;
++      client_create_listener.display = display;
++      wl_display_add_client_created_listener(display, &client_create_listener.listener);
++      ret = wl_display_add_socket_fd(display, fd);
++      assert(ret == 0);
++
++      /* Execute client that connects to the absolutely qualified server socket path. */
++      pid = fork();
++      assert(pid != -1);
++
++      if (pid == 0) {
++              ret = setenv("WAYLAND_DISPLAY", addr.sun_path, 1);
++              assert(ret == 0);
++              struct wl_display *client_display = wl_display_connect(NULL);
++              assert(client_display != NULL);
++              ret = wl_display_roundtrip(client_display);
++              assert(ret != -1);
++              wl_display_disconnect(client_display);
++              exit(0);
++              assert(false);
++      }
++
++      wl_display_run(display);
++      ret = waitpid(pid, NULL, 0);
++      assert(ret == pid);
++
++      wl_display_destroy(display);
++
++      ret = unlink(addr.sun_path);
++      assert(ret == 0);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..103ddc857ae591cae8256fd664d7b3893bf6eb86
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,535 @@@
++/*
++ * Copyright (c) 2014 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <assert.h>
++#include <errno.h>
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <stdint.h>
++#include <unistd.h>
++#include <sys/time.h>
++#include <sys/socket.h>
++#include <sys/wait.h>
++#include <signal.h>
++
++#define WL_HIDE_DEPRECATED
++
++#include "test-runner.h"
++#include "test-compositor.h"
++
++/* --- Protocol --- */
++struct test_compositor;
++
++static const struct wl_message tc_requests[] = {
++      /* this request serves as a barrier for synchronizing*/
++      { "stop_display", "u", NULL },
++      { "noop", "", NULL },
++};
++
++static const struct wl_message tc_events[] = {
++      { "display_resumed", "", NULL }
++};
++
++const struct wl_interface test_compositor_interface = {
++      "test", 1,
++      2, tc_requests,
++      1, tc_events
++};
++
++struct test_compositor_interface {
++      void (*stop_display)(struct wl_client *client,
++                           struct wl_resource *resource,
++                           uint32_t num);
++      void (*noop)(struct wl_client *client,
++                           struct wl_resource *resource);
++};
++
++struct test_compositor_listener {
++      void (*display_resumed)(void *data, struct test_compositor *tc);
++
++};
++
++enum {
++      STOP_DISPLAY = 0,
++      TEST_NOOP = 1
++};
++
++enum {
++      DISPLAY_RESUMED = 0
++};
++
++/* Since tests can run parallelly, we need unique socket names
++ * for each test, otherwise the test can fail on wl_display_add_socket. */
++static const char *
++get_socket_name(void)
++{
++      struct timeval tv;
++      static char retval[64];
++
++      gettimeofday(&tv, NULL);
++      snprintf(retval, sizeof retval, "wayland-test-%d-%ld%ld",
++               getpid(), tv.tv_sec, tv.tv_usec);
++
++      return retval;
++}
++
++static void
++handle_client_destroy(void *data)
++{
++      struct client_info *ci = data;
++      struct display *d;
++      siginfo_t status;
++
++      d = ci->display;
++
++      assert(waitid(P_PID, ci->pid, &status, WEXITED) != -1);
++
++      switch (status.si_code) {
++      case CLD_KILLED:
++      case CLD_DUMPED:
++              fprintf(stderr, "Client '%s' was killed by signal %d\n",
++                      ci->name, status.si_status);
++              ci->exit_code = status.si_status;
++              break;
++      case CLD_EXITED:
++              if (status.si_status != EXIT_SUCCESS)
++                      fprintf(stderr, "Client '%s' exited with code %d\n",
++                              ci->name, status.si_status);
++
++              ci->exit_code = status.si_status;
++              break;
++      }
++
++      ++d->clients_terminated_no;
++      if (d->clients_no == d->clients_terminated_no) {
++              wl_display_terminate(d->wl_display);
++      }
++
++      /* the clients are not removed from the list, because
++       * at the end of the test we check the exit codes of all
++       * clients. In the case that the test would go through
++       * the clients list manually, zero out the wl_client as a sign
++       * that the client is not running anymore */
++}
++
++/**
++ * Check client's state and terminate display when all clients exited
++ */
++static void
++client_destroyed(struct wl_listener *listener, void *data)
++{
++      struct client_info *ci;
++      struct display *d;
++      struct wl_event_loop *loop;
++
++      /* Wait for client in an idle handler to avoid blocking the actual
++       * client destruction (fd close etc. */
++      ci = wl_container_of(listener, ci, destroy_listener);
++      d = ci->display;
++      loop = wl_display_get_event_loop(d->wl_display);
++      wl_event_loop_add_idle(loop, handle_client_destroy, ci);
++
++      ci->wl_client = NULL;
++}
++
++static void
++run_client(void (*client_main)(void *data), void *data,
++         int wayland_sock, int client_pipe)
++{
++      char s[8];
++      int cur_fds;
++      int can_continue = 0;
++
++      /* Wait until display signals that client can continue */
++      assert(read(client_pipe, &can_continue, sizeof(int)) == sizeof(int));
++
++      if (can_continue == 0)
++              abort(); /* error in parent */
++
++      /* for wl_display_connect() */
++      snprintf(s, sizeof s, "%d", wayland_sock);
++      setenv("WAYLAND_SOCKET", s, 0);
++
++      cur_fds = count_open_fds();
++
++      client_main(data);
++
++      /* Clients using wl_display_connect() will end up closing the socket
++       * passed in through the WAYLAND_SOCKET environment variable. When
++       * doing this, it clears the environment variable, so if it's been
++       * unset, then we assume the client consumed the file descriptor and
++       * do not count it towards leak checking. */
++      if (!getenv("WAYLAND_SOCKET"))
++              cur_fds--;
++
++      check_fd_leaks(cur_fds);
++}
++
++static struct client_info *
++display_create_client(struct display *d,
++                    void (*client_main)(void *data),
++                    void *data,
++                    const char *name)
++{
++      int pipe_cli[2];
++      int sock_wayl[2];
++      pid_t pid;
++      int can_continue = 0;
++      struct client_info *cl;
++
++      assert(pipe(pipe_cli) == 0 && "Failed creating pipe");
++      assert(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_wayl) == 0
++             && "Failed creating socket pair");
++
++      pid = fork();
++      assert(pid != -1 && "Fork failed");
++
++      if (pid == 0) {
++              close(sock_wayl[1]);
++              close(pipe_cli[1]);
++
++              run_client(client_main, data, sock_wayl[0], pipe_cli[0]);
++
++              close(sock_wayl[0]);
++              close(pipe_cli[0]);
++
++              exit(0);
++      }
++
++      close(sock_wayl[0]);
++      close(pipe_cli[0]);
++
++      cl = calloc(1, sizeof(struct client_info));
++      assert(cl && "Out of memory");
++
++      wl_list_insert(&d->clients, &cl->link);
++
++      cl->display = d;
++      cl->name = name;
++      cl->pid = pid;
++      cl->pipe = pipe_cli[1];
++      cl->destroy_listener.notify = &client_destroyed;
++
++      cl->wl_client = wl_client_create(d->wl_display, sock_wayl[1]);
++      if (!cl->wl_client) {
++              int ret;
++
++              /* abort the client */
++              ret = write(cl->pipe, &can_continue, sizeof(int));
++              assert(ret == sizeof(int) && "aborting the client failed");
++              assert(0 && "Couldn't create wayland client");
++      }
++
++      wl_client_add_destroy_listener(cl->wl_client,
++                                     &cl->destroy_listener);
++
++      ++d->clients_no;
++
++      return cl;
++}
++
++struct client_info *
++client_create_with_name(struct display *d,
++                      void (*client_main)(void *data), void *data,
++                      const char *name)
++{
++      int can_continue = 1;
++      struct client_info *cl = display_create_client(d,
++                                                     client_main, data,
++                                                     name);
++
++      /* let the show begin! */
++      assert(write(cl->pipe, &can_continue, sizeof(int)) == sizeof(int));
++
++      return cl;
++}
++
++/* wfr = waiting for resume */
++struct wfr {
++      struct wl_resource *resource;
++      struct wl_list link;
++};
++
++static void
++handle_stop_display(struct wl_client *client,
++                  struct wl_resource *resource, uint32_t num)
++{
++      struct display *d = wl_resource_get_user_data(resource);
++      struct wfr *wfr;
++
++      assert(d->wfr_num < num
++             && "test error: Too many clients sent stop_display request");
++
++      ++d->wfr_num;
++
++      wfr = malloc(sizeof *wfr);
++      if (!wfr) {
++              wl_client_post_no_memory(client);
++              assert(0 && "Out of memory");
++      }
++
++      wfr->resource = resource;
++      wl_list_insert(&d->waiting_for_resume, &wfr->link);
++
++      if (d->wfr_num == num)
++              wl_display_terminate(d->wl_display);
++}
++
++static void
++handle_noop(struct wl_client *client, struct wl_resource *resource)
++{
++      (void)client;
++      (void)resource;
++}
++
++static const struct test_compositor_interface tc_implementation = {
++      handle_stop_display,
++      handle_noop,
++};
++
++static void
++tc_bind(struct wl_client *client, void *data,
++      uint32_t ver, uint32_t id)
++{
++      struct wl_resource *res;
++
++      res = wl_resource_create(client, &test_compositor_interface, ver, id);
++      if (!res) {
++              wl_client_post_no_memory(client);
++              assert(0 && "Out of memory");
++      }
++
++      wl_resource_set_implementation(res, &tc_implementation, data, NULL);
++}
++
++struct display *
++display_create(void)
++{
++      struct display *d = NULL;
++      const char *socket_name;
++      int stat = 0;
++
++      d = calloc(1, sizeof *d);
++      assert(d && "Out of memory");
++
++      d->wl_display = wl_display_create();
++      assert(d->wl_display && "Creating display failed");
++
++      /* hope the path won't be longer than 108 ... */
++      socket_name = get_socket_name();
++      stat = wl_display_add_socket(d->wl_display, socket_name);
++      assert(stat == 0 && "Failed adding socket");
++
++      wl_list_init(&d->clients);
++      d->clients_no = d->clients_terminated_no = 0;
++
++      wl_list_init(&d->waiting_for_resume);
++      d->wfr_num = 0;
++
++      d->test_global = wl_global_create(d->wl_display,
++                                        &test_compositor_interface,
++                                        1, d, tc_bind);
++      assert(d->test_global && "Creating test global failed");
++
++      return d;
++}
++
++void
++display_run(struct display *d)
++{
++      assert(d->wfr_num == 0
++             && "test error: Have waiting clients. Use display_resume.");
++      wl_display_run(d->wl_display);
++}
++
++void
++display_post_resume_events(struct display *d)
++{
++      struct wfr *wfr, *next;
++
++      assert(d->wfr_num > 0 && "test error: No clients waiting.");
++
++      wl_list_for_each_safe(wfr, next, &d->waiting_for_resume, link) {
++              wl_resource_post_event(wfr->resource, DISPLAY_RESUMED);
++              wl_list_remove(&wfr->link);
++              free(wfr);
++      }
++
++      assert(wl_list_empty(&d->waiting_for_resume));
++      d->wfr_num = 0;
++}
++
++void
++display_resume(struct display *d)
++{
++      display_post_resume_events(d);
++      wl_display_run(d->wl_display);
++}
++
++void
++display_destroy(struct display *d)
++{
++      struct client_info *cl, *next;
++      int failed = 0;
++
++      assert(d->wfr_num == 0
++             && "test error: Didn't you forget to call display_resume?");
++
++      wl_list_for_each_safe(cl, next, &d->clients, link) {
++              assert(cl->wl_client == NULL);
++
++              if (cl->exit_code != 0) {
++                      ++failed;
++                      fprintf(stderr, "Client '%s' failed\n", cl->name);
++              }
++
++              close(cl->pipe);
++              free(cl);
++      }
++
++      wl_global_destroy(d->test_global);
++      wl_display_destroy(d->wl_display);
++      free(d);
++
++      if (failed) {
++              fprintf(stderr, "%d child(ren) failed\n", failed);
++              abort();
++      }
++}
++
++/*
++ * --- Client helper functions ---
++ */
++static void
++handle_display_resumed(void *data, struct test_compositor *tc)
++{
++      struct client *c = data;
++
++      c->display_stopped = 0;
++}
++
++static const struct test_compositor_listener tc_listener = {
++      handle_display_resumed
++};
++
++static void
++registry_handle_globals(void *data, struct wl_registry *registry,
++                      uint32_t id, const char *intf, uint32_t ver)
++{
++      struct client *c = data;
++
++      if (strcmp(intf, "test") != 0)
++              return;
++
++      c->tc = wl_registry_bind(registry, id, &test_compositor_interface, ver);
++      assert(c->tc && "Failed binding to registry");
++
++      wl_proxy_add_listener((struct wl_proxy *) c->tc,
++                            (void *) &tc_listener, c);
++}
++
++static const struct wl_registry_listener registry_listener =
++{
++      registry_handle_globals,
++      NULL
++};
++
++struct client *client_connect()
++{
++      struct wl_registry *reg;
++      struct client *c = calloc(1, sizeof *c);
++      assert(c && "Out of memory");
++
++      c->wl_display = wl_display_connect(NULL);
++      assert(c->wl_display && "Failed connecting to display");
++
++      /* create test_compositor proxy. Do it with temporary
++       * registry so that client can define it's own listener later */
++      reg = wl_display_get_registry(c->wl_display);
++      assert(reg);
++      wl_registry_add_listener(reg, &registry_listener, c);
++      wl_display_roundtrip(c->wl_display);
++      assert(c->tc);
++
++      wl_registry_destroy(reg);
++
++      return c;
++}
++
++static void
++check_error(struct wl_display *display)
++{
++      uint32_t ec, id;
++      const struct wl_interface *intf;
++      int err;
++
++      err = wl_display_get_error(display);
++      /* write out message about protocol error */
++      if (err == EPROTO) {
++              ec = wl_display_get_protocol_error(display, &intf, &id);
++              fprintf(stderr, "Client: Got protocol error %u on interface %s"
++                              " (object %u)\n", ec, intf->name, id);
++      }
++
++      if (err) {
++              fprintf(stderr, "Client error: %s\n", strerror(err));
++              abort();
++      }
++}
++
++void
++client_disconnect(struct client *c)
++{
++      /* check for errors */
++      check_error(c->wl_display);
++
++      wl_proxy_destroy((struct wl_proxy *) c->tc);
++      wl_display_disconnect(c->wl_display);
++      free(c);
++}
++
++/* num is number of clients that requests to stop display.
++ * Display is stopped after it receives num STOP_DISPLAY requests */
++int
++stop_display(struct client *c, int num)
++{
++      int n = 0;
++
++      c->display_stopped = 1;
++      wl_proxy_marshal((struct wl_proxy *) c->tc, STOP_DISPLAY, num);
++
++      while (c->display_stopped && n >= 0) {
++              n = wl_display_dispatch(c->wl_display);
++      }
++
++      return n;
++}
++
++void
++noop_request(struct client *c)
++{
++      wl_proxy_marshal((struct wl_proxy *) c->tc, TEST_NOOP);
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..7b350fe9d48a336704f4f2d66b39f0a741bb52f2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,116 @@@
++/*
++ * Copyright (c) 2014 Red Hat, Inc.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include <stdint.h>
++#include <unistd.h>
++#include <stdatomic.h>
++
++#include "wayland-server.h"
++#include "wayland-client.h"
++
++/* info about a client on server side */
++struct client_info {
++      struct display *display;
++      struct wl_client *wl_client;
++      struct wl_listener destroy_listener;
++      const char *name; /* for debugging */
++
++      int pipe;
++      pid_t pid;
++      int exit_code;
++
++      struct wl_list link;
++      void *data; /* for arbitrary use */
++};
++
++struct display {
++      struct wl_display *wl_display;
++      struct wl_global *test_global;
++
++      struct wl_list clients;
++      uint32_t clients_no;
++      uint32_t clients_terminated_no;
++
++      /* list of clients waiting for display_resumed event */
++      struct wl_list waiting_for_resume;
++      uint32_t wfr_num;
++};
++
++/* This is a helper structure for clients.
++ * Instead of calling wl_display_connect() and all the other stuff,
++ * client can use client_connect and it will return this structure
++ * filled. */
++struct client {
++      struct wl_display *wl_display;
++      struct test_compositor *tc;
++
++      atomic_bool display_stopped;
++};
++
++struct client *client_connect(void);
++void client_disconnect(struct client *);
++int stop_display(struct client *, int);
++void noop_request(struct client *);
++
++/**
++ * Usual workflow:
++ *
++ *    d = display_create();
++ *
++ *    wl_global_create(d->wl_display, ...);
++ *    ... other setups ...
++ *
++ *    client_create(d, client_main, data);
++ *    client_create(d, client_main2, data);
++ *
++ *    display_run(d);
++ *    display_destroy(d);
++ */
++struct display *display_create(void);
++void display_destroy(struct display *d);
++void display_run(struct display *d);
++
++/* This function posts the display_resumed event to all waiting clients,
++ * so that after flushing events the clients will stop waiting and continue.
++ *
++ * (Calling `display_run` after this function will resume the display loop.)
++ */
++void display_post_resume_events(struct display *d);
++/* After n clients called stop_display(..., n), the display
++ * is stopped and can process the code after display_run().
++ *
++ * This function posts the display_resumed event to the waiting
++ * clients, so that the clients will stop waiting and continue;
++ * it then reruns the display. */
++void display_resume(struct display *d);
++
++
++struct client_info *client_create_with_name(struct display *d,
++                                          void (*client_main)(void *data),
++                                          void *data,
++                                          const char *name);
++#define client_create(d, c, data) client_create_with_name((d), (c), data, (#c))
++#define client_create_noarg(d, c) \
++      client_create_with_name((d), (void(*)(void *)) (c), NULL, (#c))
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..353574450be2f893d843e4d8e73d8c3065d7f4e2
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,164 @@@
++/*
++ * Copyright © 2012 Collabora, Ltd.
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++
++#include "config.h"
++
++#include <assert.h>
++#include <errno.h>
++#include <dirent.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <time.h>
++#include <sys/time.h>
++#include <sys/resource.h>
++
++#ifdef HAVE_SYS_PRCTL_H
++#include <sys/prctl.h>
++#endif
++
++#include "test-runner.h"
++
++#if defined(__FreeBSD__)
++#include <sys/sysctl.h>
++
++/*
++ * On FreeBSD, get file descriptor information using sysctl() since that does
++ * not depend on a mounted fdescfs (which provides /dev/fd/N for N > 2).
++ */
++int
++count_open_fds(void)
++{
++      int error;
++      int nfds;
++      int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_NFDS, 0 };
++      size_t len;
++
++      len = sizeof(nfds);
++      error = sysctl(mib, 4, &nfds, &len, NULL, 0);
++      assert(error == 0 && "sysctl KERN_PROC_NFDS failed.");
++      return nfds;
++}
++#else
++int
++count_open_fds(void)
++{
++      DIR *dir;
++      struct dirent *ent;
++      int count = 0;
++
++      /*
++       * Using /dev/fd instead of /proc/self/fd should allow this code to
++       * work on non-Linux operating systems.
++       */
++      dir = opendir("/dev/fd");
++      assert(dir && "opening /dev/fd failed.");
++
++      errno = 0;
++      while ((ent = readdir(dir))) {
++              const char *s = ent->d_name;
++              if (s[0] == '.' && (s[1] == 0 || (s[1] == '.' && s[2] == 0)))
++                      continue;
++              count++;
++      }
++      assert(errno == 0 && "reading /dev/fd failed.");
++
++      closedir(dir);
++
++      return count;
++}
++#endif
++
++void
++exec_fd_leak_check(int nr_expected_fds)
++{
++      const char *exe = "exec-fd-leak-checker";
++      char number[16] = { 0 };
++      const char *test_build_dir = getenv("TEST_BUILD_DIR");
++      char exe_path[256] = { 0 };
++
++      if (test_build_dir == NULL || test_build_dir[0] == 0) {
++              test_build_dir = ".";
++      }
++
++      snprintf(exe_path, sizeof exe_path - 1, "%s/%s", test_build_dir, exe);
++
++      snprintf(number, sizeof number - 1, "%d", nr_expected_fds);
++      execl(exe_path, exe, number, (char *)NULL);
++      assert(0 && "execing fd leak checker failed");
++}
++
++#define USEC_TO_NSEC(n) (1000 * (n))
++
++/* our implementation of usleep and sleep functions that are safe to use with
++ * timeouts (timeouts are implemented using alarm(), so it is not safe use
++ * usleep and sleep. See man pages of these functions)
++ */
++void
++test_usleep(useconds_t usec)
++{
++      struct timespec ts = {
++              .tv_sec = 0,
++              .tv_nsec = USEC_TO_NSEC(usec)
++      };
++
++      assert(nanosleep(&ts, NULL) == 0);
++}
++
++/* we must write the whole function instead of
++ * wrapping test_usleep, because useconds_t may not
++ * be able to contain such a big number of microseconds */
++void
++test_sleep(unsigned int sec)
++{
++      struct timespec ts = {
++              .tv_sec = sec,
++              .tv_nsec = 0
++      };
++
++      assert(nanosleep(&ts, NULL) == 0);
++}
++
++/** Try to disable coredumps
++ *
++ * Useful for tests that crash on purpose, to avoid creating a core file
++ * or launching an application crash handler service or cluttering coredumpctl.
++ *
++ * NOTE: Calling this may make the process undebuggable.
++ */
++void
++test_disable_coredumps(void)
++{
++      struct rlimit r;
++
++      if (getrlimit(RLIMIT_CORE, &r) == 0) {
++              r.rlim_cur = 0;
++              setrlimit(RLIMIT_CORE, &r);
++      }
++
++#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
++      prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
++#endif
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d07dab1597f61a97237ea42fb34a05edd7e2ba59
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,414 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#include "../config.h"
++
++#define _GNU_SOURCE
++
++#include <unistd.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <sys/stat.h>
++#include <string.h>
++#include <assert.h>
++#include <dlfcn.h>
++#include <errno.h>
++#include <limits.h>
++#include <signal.h>
++#include <sys/ptrace.h>
++#ifdef HAVE_SYS_PROCCTL_H
++#include <sys/procctl.h>
++#elif defined(HAVE_SYS_PRCTL_H)
++#include <sys/prctl.h>
++#ifndef PR_SET_PTRACER
++# define PR_SET_PTRACER 0x59616d61
++#endif
++#endif
++
++#include "test-runner.h"
++
++/* when set to 1, check if tests are not leaking opened files.
++ * It is turned on by default. It can be turned off by
++ * WAYLAND_TEST_NO_LEAK_CHECK environment variable. */
++int fd_leak_check_enabled;
++
++/* when this var is set to 0, every call to test_set_timeout() is
++ * suppressed - handy when debugging the test. Can be set by
++ * WAYLAND_TEST_NO_TIMEOUTS environment variable. */
++static int timeouts_enabled = 1;
++
++/* set to one if the output goes to the terminal */
++static int is_atty = 0;
++
++extern const struct test __start_test_section, __stop_test_section;
++
++static const struct test *
++find_test(const char *name)
++{
++      const struct test *t;
++
++      for (t = &__start_test_section; t < &__stop_test_section; t++)
++              if (strcmp(t->name, name) == 0)
++                      return t;
++
++      return NULL;
++}
++
++static void
++usage(const char *name, int status)
++{
++      const struct test *t;
++
++      fprintf(stderr, "Usage: %s [TEST]\n\n"
++              "With no arguments, run all test.  Specify test case to run\n"
++              "only that test without forking.  Available tests:\n\n",
++              name);
++
++      for (t = &__start_test_section; t < &__stop_test_section; t++)
++              fprintf(stderr, "  %s\n", t->name);
++
++      fprintf(stderr, "\n");
++
++      exit(status);
++}
++
++void
++test_set_timeout(unsigned int to)
++{
++      int re;
++
++      if (!timeouts_enabled) {
++              fprintf(stderr, "Timeouts suppressed.\n");
++              return;
++      }
++
++      re = alarm(to);
++      fprintf(stderr, "Timeout was %sset", re ? "re-" : "");
++
++      if (to != 0)
++              fprintf(stderr, " to %d second%s from now.\n",
++                      to, to > 1 ? "s" : "");
++      else
++              fprintf(stderr, " off.\n");
++}
++
++static void
++sigalrm_handler(int signum)
++{
++      fprintf(stderr, "Test timed out.\n");
++      abort();
++}
++
++void
++check_fd_leaks(int supposed_fds)
++{
++      int num_fds;
++
++      if (fd_leak_check_enabled) {
++              num_fds = count_open_fds();
++              if (supposed_fds != num_fds) {
++                      fprintf(stderr, "fd leak detected in test. "
++                              "Opened %d files, unclosed %d\n", num_fds,
++                              num_fds - supposed_fds);
++                      abort();
++              }
++      } else {
++              fprintf(stderr, "FD leak checks disabled\n");
++      }
++}
++
++static void
++run_test(const struct test *t)
++{
++      int cur_fds;
++      struct sigaction sa;
++
++      if (timeouts_enabled) {
++              sa.sa_handler = sigalrm_handler;
++              sa.sa_flags = 0;
++              sigemptyset(&sa.sa_mask);
++              assert(sigaction(SIGALRM, &sa, NULL) == 0);
++      }
++
++      //cur_alloc = get_current_alloc_num();
++      cur_fds = count_open_fds();
++
++      t->run();
++
++      /* turn off timeout (if any) after test completion */
++      if (timeouts_enabled)
++              alarm(0);
++
++      check_fd_leaks(cur_fds);
++
++      exit(EXIT_SUCCESS);
++}
++
++#ifndef PATH_MAX
++#define PATH_MAX 256
++#endif
++
++static void
++set_xdg_runtime_dir(void)
++{
++      char xdg_runtime_dir[PATH_MAX];
++      const char *xrd_env;
++
++      xrd_env = getenv("XDG_RUNTIME_DIR");
++      /* if XDG_RUNTIME_DIR is not set in environ, fallback to /tmp */
++      assert((snprintf(xdg_runtime_dir, PATH_MAX, "%s/wayland-tests-XXXXXX",
++                       (xrd_env && xrd_env[0] == '/') ? xrd_env : "/tmp") < PATH_MAX)
++              && "test error: XDG_RUNTIME_DIR too long");
++
++      assert(mkdtemp(xdg_runtime_dir) && "test error: mkdtemp failed");
++      if (mkdir(xdg_runtime_dir, 0700) == -1)
++              if (errno != EEXIST) {
++                      perror("Creating XDG_RUNTIME_DIR");
++                      abort();
++              }
++
++      if (setenv("XDG_RUNTIME_DIR", xdg_runtime_dir, 1) == -1) {
++              perror("Setting XDG_RUNTIME_DIR");
++              abort();
++      }
++}
++
++static void
++rmdir_xdg_runtime_dir(void)
++{
++      const char *xrd_env = getenv("XDG_RUNTIME_DIR");
++      assert(xrd_env && xrd_env[0] == '/' && "No XDG_RUNTIME_DIR set");
++
++      /* rmdir may fail if some test didn't do clean up */
++      if (rmdir(xrd_env) == -1)
++              perror("Cleaning XDG_RUNTIME_DIR");
++}
++
++#define RED   "\033[31m"
++#define GREEN "\033[32m"
++
++static void
++stderr_set_color(const char *color)
++{
++      /* use colors only when the output is connected to
++       * the terminal */
++      if (is_atty)
++              fprintf(stderr, "%s", color);
++}
++
++static void
++stderr_reset_color(void)
++{
++      if (is_atty)
++              fprintf(stderr, "\033[0m");
++}
++
++/* this function is taken from libinput/test/litest.c
++ * (rev 028513a0a723e97941c39)
++ *
++ * Returns: 1 if a debugger is confirmed present; 0 if no debugger is
++ * present or if it can't be determined.
++ */
++#if defined(HAVE_SYS_PROCCTL_H) && defined(PROC_TRACE_STATUS)
++static int
++is_debugger_attached(void)
++{
++      int rc;
++      int status;
++      rc = procctl(P_PID, getpid(), PROC_TRACE_STATUS, &status);
++      if (rc == -1) {
++              perror("procctl");
++              return 0;
++      }
++      /* -1=tracing disabled, 0=no debugger attached, >0=pid of debugger. */
++      return status > 0;
++}
++#elif defined(HAVE_SYS_PRCTL_H)
++static int
++is_debugger_attached(void)
++{
++      int status;
++      int rc;
++      pid_t pid;
++      int pipefd[2];
++
++      if (pipe(pipefd) == -1) {
++              perror("pipe");
++              return 0;
++      }
++
++      pid = fork();
++      if (pid == -1) {
++              perror("fork");
++              close(pipefd[0]);
++              close(pipefd[1]);
++              return 0;
++      } else if (pid == 0) {
++              char buf;
++              pid_t ppid = getppid();
++
++              /* Wait until parent is ready */
++              close(pipefd[1]);  /* Close unused write end */
++              read(pipefd[0], &buf, 1);
++              close(pipefd[0]);
++              if (buf == '-')
++                      _exit(1);
++              if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) != 0)
++                      _exit(1);
++              if (!waitpid(-1, NULL, 0))
++                      _exit(1);
++              ptrace(PTRACE_CONT, NULL, NULL);
++              ptrace(PTRACE_DETACH, ppid, NULL, NULL);
++              _exit(0);
++      } else {
++              close(pipefd[0]);
++
++              /* Enable child to ptrace the parent process */
++              rc = prctl(PR_SET_PTRACER, pid);
++              if (rc != 0 && errno != EINVAL) {
++                      /* An error prevents us from telling if a debugger is attached.
++                       * Instead of propagating the error, assume no debugger present.
++                       * But note the error to the log as a clue for troubleshooting.
++                       * Then flag the error state to the client by sending '-'.
++                       */
++                      perror("prctl");
++                      write(pipefd[1], "-", 1);
++              } else {
++                      /* Signal to client that parent is ready by passing '+' */
++                      write(pipefd[1], "+", 1);
++              }
++              close(pipefd[1]);
++
++              waitpid(pid, &status, 0);
++              rc = WEXITSTATUS(status);
++      }
++
++      return rc;
++}
++#endif
++
++int main(int argc, char *argv[])
++{
++      const struct test *t;
++      pid_t pid;
++      int total, pass;
++      siginfo_t info;
++
++      if (isatty(fileno(stderr)))
++              is_atty = 1;
++
++      if (is_debugger_attached()) {
++              fd_leak_check_enabled = 0;
++              timeouts_enabled = 0;
++      } else {
++              fd_leak_check_enabled = !getenv("WAYLAND_TEST_NO_LEAK_CHECK");
++              timeouts_enabled = !getenv("WAYLAND_TEST_NO_TIMEOUTS");
++      }
++
++      if (argc == 2 && strcmp(argv[1], "--help") == 0)
++              usage(argv[0], EXIT_SUCCESS);
++
++      if (argc == 2) {
++              t = find_test(argv[1]);
++              if (t == NULL) {
++                      fprintf(stderr, "unknown test: \"%s\"\n", argv[1]);
++                      usage(argv[0], EXIT_FAILURE);
++              }
++
++              set_xdg_runtime_dir();
++              /* run_test calls exit() */
++              assert(atexit(rmdir_xdg_runtime_dir) == 0);
++
++              run_test(t);
++      }
++
++      /* set our own XDG_RUNTIME_DIR */
++      set_xdg_runtime_dir();
++
++      pass = 0;
++      for (t = &__start_test_section; t < &__stop_test_section; t++) {
++              int success = 0;
++
++              pid = fork();
++              assert(pid >= 0);
++
++              if (pid == 0)
++                      run_test(t); /* never returns */
++
++              if (waitid(P_PID, pid, &info, WEXITED)) {
++                      stderr_set_color(RED);
++                      fprintf(stderr, "waitid failed: %s\n",
++                              strerror(errno));
++                      stderr_reset_color();
++
++                      abort();
++              }
++
++              switch (info.si_code) {
++              case CLD_EXITED:
++                      if (info.si_status == EXIT_SUCCESS)
++                              success = !t->must_fail;
++                      else
++                              success = t->must_fail;
++
++                      stderr_set_color(success ? GREEN : RED);
++                      fprintf(stderr, "test \"%s\":\texit status %d",
++                              t->name, info.si_status);
++
++                      break;
++              case CLD_KILLED:
++              case CLD_DUMPED:
++                      if (t->must_fail)
++                              success = 1;
++
++                      stderr_set_color(success ? GREEN : RED);
++                      fprintf(stderr, "test \"%s\":\tsignal %d",
++                              t->name, info.si_status);
++
++                      break;
++              }
++
++              if (success) {
++                      pass++;
++                      fprintf(stderr, ", pass.\n");
++              } else
++                      fprintf(stderr, ", fail.\n");
++
++              stderr_reset_color();
++
++              /* print separator line */
++              fprintf(stderr, "----------------------------------------\n");
++      }
++
++      total = &__stop_test_section - &__start_test_section;
++      fprintf(stderr, "%d tests, %d pass, %d fail\n",
++              total, pass, total - pass);
++
++      /* cleaning */
++      rmdir_xdg_runtime_dir();
++
++      return pass == total ? EXIT_SUCCESS : EXIT_FAILURE;
++}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..d0734009601e8d7462e8b837996bda01a299ef6e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,95 @@@
++/*
++ * Copyright © 2012 Intel Corporation
++ *
++ * Permission is hereby granted, free of charge, to any person obtaining
++ * a copy of this software and associated documentation files (the
++ * "Software"), to deal in the Software without restriction, including
++ * without limitation the rights to use, copy, modify, merge, publish,
++ * distribute, sublicense, and/or sell copies of the Software, and to
++ * permit persons to whom the Software is furnished to do so, subject to
++ * the following conditions:
++ *
++ * The above copyright notice and this permission notice (including the
++ * next paragraph) shall be included in all copies or substantial
++ * portions of the Software.
++ *
++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
++ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
++ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
++ * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
++ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
++ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
++ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
++ * SOFTWARE.
++ */
++#ifndef _TEST_RUNNER_H_
++#define _TEST_RUNNER_H_
++
++#ifdef NDEBUG
++#error "Tests must not be built with NDEBUG defined, they rely on assert()."
++#endif
++
++#include <unistd.h>
++
++struct test {
++      const char *name;
++      void (*run)(void);
++      int must_fail;
++} __attribute__ ((aligned (16)));
++
++#define TEST(name)                                                    \
++      static void name(void);                                         \
++                                                                      \
++      const struct test test##name                                    \
++               __attribute__ ((used, section ("test_section"))) = {   \
++              #name, name, 0                                          \
++      };                                                              \
++                                                                      \
++      static void name(void)
++
++#define FAIL_TEST(name)                                                       \
++      static void name(void);                                         \
++                                                                      \
++      const struct test test##name                                    \
++               __attribute__ ((used, section ("test_section"))) = {   \
++              #name, name, 1                                          \
++      };                                                              \
++                                                                      \
++      static void name(void)
++
++int
++count_open_fds(void);
++
++void
++exec_fd_leak_check(int nr_expected_fds); /* never returns */
++
++void
++check_fd_leaks(int supposed_fds);
++
++/*
++ * set/reset the timeout in seconds. The timeout starts
++ * at the point of invoking this function
++ */
++void
++test_set_timeout(unsigned int);
++
++/* test-runner uses alarm() and SIGALRM, so we can not
++ * use usleep and sleep functions in tests (see 'man usleep'
++ * or 'man sleep', respectively). Following functions are safe
++ * to use in tests */
++void
++test_usleep(useconds_t);
++
++void
++test_sleep(unsigned int);
++
++void
++test_disable_coredumps(void);
++
++#define DISABLE_LEAK_CHECKS                           \
++      do {                                            \
++              extern int fd_leak_check_enabled;       \
++              fd_leak_check_enabled = 0;              \
++      } while (0);
++
++#endif
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..2b222e8bd58b6584a4faed936df18e83ef11e9ae
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,13 @@@
++AC_DEFUN([WAYLAND_SCANNER_RULES], [
++    PKG_PROG_PKG_CONFIG
++
++    PKG_CHECK_MODULES([WAYLAND_SCANNER], [wayland-scanner >= 1.14.0])
++
++    wayland_scanner=`$PKG_CONFIG --variable=wayland_scanner wayland-scanner`
++    AC_SUBST([wayland_scanner])
++
++    wayland_scanner_rules=`$PKG_CONFIG --variable=pkgdatadir wayland-scanner`/wayland-scanner.mk
++    AC_SUBST_FILE([wayland_scanner_rules])
++
++    AC_SUBST([wayland_protocoldir], [$1])
++])
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c174e6bd726b524d95c38b46cbbfbded4a65c977
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,8 @@@
++%-protocol.c : $(wayland_protocoldir)/%.xml
++      $(AM_V_GEN)$(wayland_scanner) code $< $@
++
++%-server-protocol.h : $(wayland_protocoldir)/%.xml
++      $(AM_V_GEN)$(wayland_scanner) server-header $< $@
++
++%-client-protocol.h : $(wayland_protocoldir)/%.xml
++      $(AM_V_GEN)$(wayland_scanner) client-header $< $@